<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Prequel's Blogs]]></title><description><![CDATA[Prequel's Blogs]]></description><link>https://prequel.hashnode.dev</link><generator>RSS for Node</generator><lastBuildDate>Mon, 14 Sep 2026 18:58:48 GMT</lastBuildDate><atom:link href="https://prequel.hashnode.dev/rss.xml" rel="self" type="application/rss+xml"/><language><![CDATA[en]]></language><ttl>60</ttl><item><title><![CDATA[The Real State of Helm Chart Reliability (2025): Hidden Risks in 100+ Open‑Source Charts]]></title><description><![CDATA[tldr

Prequel's reliability research team audited 105 popular Kubernetes Helm charts to reveal missing reliability safeguards.

The average score was ~3.98/10

48% (50 charts) rated "High Risk" (score ≤3/10)

Only 17% (18 charts) were rated "Reliable...]]></description><link>https://prequel.hashnode.dev/the-real-state-of-helm-chart-reliability-2025-hidden-risks-in-100-opensource-charts</link><guid isPermaLink="true">https://prequel.hashnode.dev/the-real-state-of-helm-chart-reliability-2025-hidden-risks-in-100-opensource-charts</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Reliability]]></category><category><![CDATA[SRE]]></category><category><![CDATA[Open Source]]></category><dc:creator><![CDATA[Lyndon Brown]]></dc:creator><pubDate>Tue, 04 Nov 2025 20:06:55 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286367013/be6ade5b-c1a2-4d0c-98d5-ff6f154ab507.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h1 id="heading-tldr">tldr</h1>
<ul>
<li><p><a target="_blank" href="https://www.prequel.dev"><strong>Prequel</strong></a>'s reliability research team audited 105 popular Kubernetes Helm charts to reveal missing reliability safeguards.</p>
<ul>
<li><p>The average score was ~3.98/10</p>
</li>
<li><p>48% (50 charts) rated "High Risk" (score ≤3/10)</p>
</li>
<li><p>Only 17% (18 charts) were rated "Reliable" (≥7/10)</p>
</li>
</ul>
</li>
<li><p><strong>Key missing features include</strong></p>
<ul>
<li><p>Pod Topology Spread Constraints (93% absent)</p>
</li>
<li><p>PodDisruptionBudget (74% absent)</p>
</li>
<li><p>Horizontal Pod Autoscalers (75% absent)</p>
</li>
<li><p>CPU/Memory resource requests/limits (50–60% absent)</p>
</li>
</ul>
</li>
<li><p>Several 0/10 charts were DaemonSets (e.g., Fluent Bit, node-exporter, GPU plugins) where PDB/TopologySpread/HPA/Replicas are generally not applicable.</p>
</li>
<li><p>It’s important to note that a low score does not necessarily mean the software itself is bad; rather, it means the default deployment setup might not offer high reliability standards.</p>
</li>
<li><p>We recommend end users patch missing controls via <code>values.yaml</code> or via Helm overlays.</p>
</li>
<li><p>Users should use continuous reliability protection tools like <strong>Prequel</strong> to identify missing safeguards and monitor for impact.</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286409850/38d7a710-e0e0-4cba-87a5-ab6540b250b4.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-introduction"><strong>Introduction</strong></h2>
<p>Reliability is one of the main reasons teams adopt Kubernetes, it promises self-healing workloads, automated rollouts, and consistent recovery across environments. However, it is easy to undercut these advantages. A Helm chart packages the Kubernetes manifests that define how an application is deployed. When those charts omit best practices or include misconfigurations, the resulting deployments can become unreliable.</p>
<p>This report presents a comprehensive reliability audit of 105 popular Helm charts. The goal is to identify how well these charts adhere to known best practices that improve uptime, resiliency, and safe operations in Kubernetes environments.</p>
<p><strong>What do we mean by "reliability" in this context?</strong> Essentially, we looked for Kubernetes manifest settings that help applications <strong>survive disruptions, autoscale to handle load, and avoid common failure modes</strong>. These settings correspond to widely recommended practices such as configuring PodDisruptionBudgets, spreading pods across zones and nodes, defining CPU/Memory requests, enabling Horizontal Pod Autoscaling with sensible minimums, etc. When these features are properly set, applications are better protected against outages (both planned and unplanned).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286433048/21c0009a-5184-416d-b151-9845b5a018b9.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-how-did-we-collect-the-data"><strong>How did we collect the data?</strong></h2>
<p>The Prequel Reliability Research Team (PRRT) evaluated a total of <strong>105 Helm charts</strong>, selected to cover a broad range of popular open-source applications and infrastructure components. These include charts for observability tools (e.g. Grafana, Prometheus), databases and storage systems (e.g. MySQL, Elasticsearch), networking and security add-ons (e.g. NGINX Ingress, Calico), messaging systems (e.g. Kafka, Pulsar), machine learning tools, and more. Each chart was analyzed using both its default manifests and a minimal "HA‑capability" render to reveal what's supported when scaled.</p>
<h2 id="heading-what-was-our-criteria"><strong>What was our criteria?</strong></h2>
<p>We checked each chart against <strong>10 key reliability criteria</strong>. Each criterion corresponds to a best-practice configuration that improves reliability. Each chart was rendered twice: once with default values (out-of-the-box) and once with a minimal "HA-capability" override (e.g., setting replicaCount/replicas ≥ 2 and enabling autoscaling/HPA when available). Capability-style criteria (PDB, TopologySpreadConstraints, HPA) are considered "preseConsider writing an overlay chart or a wrapper that adds missing pieces.</p>
<p><strong>Note</strong>: <em>Daemonset(DS)‑based charts do not use PDB, TopologySpreadConstraints, HPA, or Replicas in the same way as Deployments/StatefulSets. For DS we emphasize CPU/Memory Requests/Limits and Liveness. Interpret DS scores with this in mind.</em></p>
<p>The specific criteria audited were:</p>
<ul>
<li><p><strong>PodDisruptionBudget (PDB)</strong> - Does the chart define a PodDisruptionBudget for its pods? A PDB ensures that a <em>minimum number of pods stay up during voluntary disruptions</em> (like node drains or upgrades), so that maintenance events don't accidentally take down the entire application[2].</p>
<ul>
<li>a PDB <em>limits</em> how many pods can be offline at once, preserving availability[3].</li>
</ul>
</li>
<li><p><strong>Topology Spread Constraints</strong> (N/A for DaemonSets ;one pod per node; spread is implicit) - Does the chart use topologySpreadConstraints to spread replicas across nodes/zones? This feature prevents all pods from landing on the same node or zone. By distributing pods across failure domains, it <strong>reduces the blast radius</strong> - if one node or AZ goes down, it won't take out every replica[4].</p>
<ul>
<li>Topology spread constraints thus improve resiliency in multi-node or multi-zone clusters.</li>
</ul>
</li>
<li><p><strong>Horizontal Pod Autoscaler (HPA)</strong> (N/A for DaemonSets; HPA does not scale DS) - Does the chart include a HorizontalPodAutoscaler resource (or support enabling it via values)? An HPA will automatically adjust the number of pod replicas based on workload (CPU, memory, or custom metrics)[5].</p>
<ul>
<li>This ensures the application can scale out to handle surges in demand and scale back down to save resources, thereby preventing overload and maintaining performance during peak loads. In practice, an HPA with minReplicas ≥ 2 will ensure redundancy.</li>
</ul>
</li>
<li><p><strong>CPU Requests</strong> - Do the pods have CPU requests set? A CPU request reserves a certain amount of CPU for the container. Setting requests is vital because it lets the Kubernetes scheduler know the pod's needs, and prevents scheduling too many high-demand pods on one node.</p>
<ul>
<li>Without CPU requests, pods might be squeezed onto a node without guaranteed compute, leading to unpredictability. We treat absence of CPU requests as a reliability risk.</li>
</ul>
</li>
<li><p><strong>CPU Limits</strong> - Do the pods have CPU limits defined? CPU limits cap how much CPU time a container can use. This is important to prevent a single pod from monopolizing the CPU on a node.</p>
<ul>
<li><p>Left unchecked, a misbehaving pod can starve co‑located workloads (including system components), hurting overall cluster stability.</p>
<ul>
<li><strong>Note</strong>: <em>The use of CPU limits is debated; limits can introduce CPU throttling under load (sometimes even when usage appears within the configured limit), which may cause latency spikes. We still treat the presence of reasonable limits as a reliability factor because they improve predictability and blast‑radius control.</em></li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Memory Requests</strong> - Do the pods have memory requests set? Like CPU requests, memory requests ensure the scheduler gives the pod a guaranteed amount of RAM. This helps avoid scenarios where too many memory-hungry pods are placed on one node, which could lead to OOM (Out-Of-Memory) kills or node instability if memory is overcommitted. Charts should specify memory requests for reliability.</p>
</li>
<li><p><strong>Memory Limits</strong> - Do the pods have memory limits? A memory limit puts an upper bound on memory usage for a container. This prevents a runaway process from consuming all available memory on the node.</p>
<ul>
<li>Without a memory limit, a single container can trigger out-of-memory conditions that crash itself or even the node. Setting memory limits thus contains faults and improves resilience.</li>
</ul>
</li>
<li><p><strong>Liveness Probe</strong> - Does the container include a liveness probe (heartbeat check)? Liveness probes allow Kubernetes to detect if an application has hung or crashed internally. If the liveness probe fails, Kubernetes will automatically restart the container[7][8].</p>
<ul>
<li>This self-healing mechanism is crucial for reliability, ensuring that issues like deadlocks or crashes don't go unnoticed.</li>
</ul>
</li>
<li><p><strong>Readiness Probe</strong> (Usually N/A for DaemonSets; often no Service)- Does the container include a readiness probe? A readiness probe signals when a pod is ready to serve traffic. Kubernetes will not send traffic to a pod (for example, attach it to a Service load balancer) until its readiness probe succeeds.</p>
<ul>
<li><p>This prevents sending requests to pods that are still initializing or are unhealthy[8]. In our context, having readiness probes means smoother rollouts and no premature traffic to unready pods, avoiding potential errors during startup or local disruptions.</p>
<ul>
<li><strong>Note:</strong> <em>readiness can also fail after startup to indicate momentary unavailability; the pod will not be restarted as long as the liveness probe continues to succeed.</em></li>
</ul>
</li>
</ul>
</li>
<li><p><strong>PriorityClass</strong> - Does the chart assign a PriorityClass to its pods? Priority classes determine the priority of pods for scheduling and eviction. Using a PriorityClass for critical workloads ensures that in resource crunch scenarios, <strong>lower-priority pods won't displace or interfere with more critical pods</strong>[9].</p>
<ul>
<li><p>Essentially, it helps protect mission-critical applications from being preempted or starved by less important ones[9]. While not every application needs a custom priority, setting one for system-critical services can improve reliability during cluster stress.</p>
</li>
<li><p><strong>Note</strong>: <em>we present PriorityClass as informational and do not score it by default. But for Daemonset based charts they can be considered a reliability constraint.</em></p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-how-did-we-score-charts">How did we score charts?</h3>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286444271/cd9739af-be87-4804-aeaa-80e76425143a.png" alt class="image--center mx-auto" /></p>
<p>Each Helm chart was evaluated against the 9 scored criteria (all of the above except PriorityClass). For each scored criterion present, the chart earned 1 point. Thus, charts could score between 0 (none of the best practices present) and 9 (all scored practices present). We then categorized charts into reliability tiers based on their score: - <strong>"Reliable"</strong> - Score of 7 or above (i.e., implementing at least ~75% of the scored practices). These charts have most of the important safeguards in place. <strong>"Moderate"</strong> - Score of 4 to 6. These charts follow some best practices but lack others, indicating room for improvement. <strong>"High Risk"</strong> - Score of 3 or below. Such charts miss the majority of reliability features, likely making them fragile in real-world conditions.</p>
<p>It's important to note that a low score does not necessarily mean the software itself is bad; rather, it means the <strong>default Kubernetes manifests provided by the Helm chart might not ensure high availability or resilience</strong>. Users could still deploy those applications reliably by tweaking configurations (e.g., enabling HPA or increasing replicas), but out-of-the-box, the chart might expose them to more risk.</p>
<p>For this report, we opted not to add weights to the various safeguards.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286469622/5144a146-499d-4c8e-a6ad-d1191a6f4034.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-overall-reliability-scores"><strong>Overall Reliability Scores</strong></h2>
<p>Across the 105 Helm charts evaluated, the distribution of reliability scores was skewed toward the lower end. The <strong>mean score was ~3.98 out of 10</strong>, and the <strong>median score was 4</strong>, indicating that typically a chart only implements around four of the ten recommended reliability measures.</p>
<p>This overall low average suggests that many popular Helm charts do not incorporate a comprehensive set of reliability features by default.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286476412/bfdf001c-a7ad-49a7-954d-b63b32b3d22e.png" alt class="image--center mx-auto" /></p>
<p>To put these results in perspective:</p>
<ul>
<li><p>Only <strong>18 charts (17.1%)</strong> scored in the <strong>"Reliable" tier</strong>, meeting 7 or more of the criteria. In fact, the highest score observed was 9/10 (no chart had a perfect 10). This means very few charts have almost all the best practices in place. The top scorers tend to be well-maintained projects that explicitly focus on robust deployments (examples are discussed later).</p>
</li>
<li><p><strong>37 charts (35.2%)</strong> fell into the <strong>"Moderate" tier</strong> with scores 4-6. These charts include some reliability features but are missing many others. They might, for instance, have health probes configured but lack autoscaling and disruption budgets, or vice versa.</p>
</li>
<li><p><strong>50 charts (47.6%)</strong> landed in the <strong>"High Risk" tier</strong> with a score of 3 or below.</p>
</li>
</ul>
<p>Alarmingly, nearly half of the charts audited implement only a few (if any) of the reliability best practices. In fact, 10 charts scored <strong>0/10</strong>, meaning they <em>did not</em> include a single one of the checked reliability features in their default manifests.</p>
<p>On the other hand, the relatively small fraction of charts in the "Reliable" tier demonstrates that <strong>it is feasible</strong> for a Helm chart to be shipped with strong reliability guardrails so this is an attainable goal for chart maintainers. The findings suggest that there's significant room for improvement across the board, and users should not assume a chart is production-ready just because it's popular.</p>
<p>In summary, the overall reliability state of Helm charts is <strong>middling to poor</strong>, with a heavy tail of charts lacking critical features. Next, we delve into which specific reliability practices are most often absent, and which are more commonly implemented.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286492483/5dd4def9-534b-47ef-9712-7c79a9dde9f0.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-whats-missing-most-often"><strong>What's Missing Most Often</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286506981/8a897b6a-937f-4d7b-9f8c-8ff7778d3023.png" alt class="image--center mx-auto" /></p>
<p>Looking at the pass/fail rates for each of the 10 criteria gives insight into which reliability practices chart maintainers commonly omit. The following are the key criteria, ordered from <strong>most neglected</strong> to most adopted, along with the percentage of charts that <strong>failed</strong> each check in our audit (<strong>note</strong>: for capability-style criteria like PDB/TopologySpread/HPA, we count them as present if found either in the default render or under a minimal HA-capability render):</p>
<ul>
<li><p><strong>Topology Spread Constraints - 93%</strong> of charts <em>do not</em> specify any topology spread constraints. This was the most glaring gap: only about 7% of charts had this configuration. Essentially, almost all charts do nothing to ensure pods are spread across multiple nodes or zones.</p>
<ul>
<li><p>As a result, if you deploy these charts, there's a high chance all replicas could land on a single node by default, making the application vulnerable to node-level failures.</p>
</li>
<li><p><strong>Note:</strong> <em>We didn't score podAntiAffinity. While it can reduce co-location, it often over‑constrains scheduling and can slow recovery during drains/outages. We focus on topologySpreadConstraints (more expressive and preferred) and may surface podAntiAffinity as informational in future iterations.</em></p>
</li>
</ul>
</li>
<li><p><strong>Horizontal Pod Autoscaler (HPA) - 75%</strong> of charts lack an HPA. Three out of four charts do not provide an automated scaling policy. This means by default those applications will run a fixed number of replicas regardless of whether the charts had this configuration. Essentially, almost all charts do nothing to ensure pods are spread across multiple nodes or zones.</p>
<ul>
<li><p>As a result, if you deploy these charts, there's a high chance all replicas could land on a single node by default, making the application vulnerable to node-level failures. (We detect constraints both at the top level (spec.template) and in pod templates ( spec.topologySpreadConstraints.)load.</p>
</li>
<li><p>If there's a traffic surge or high workload, the application won't scale out to handle it, potentially leading to performance degradation or downtime. In our evaluation, an HPA with minReplicas ≥ 2 is considered to provide redundancy; the low inclusion rate suggests many charts expect users to enable scaling themselves.</p>
</li>
</ul>
</li>
<li><p><strong>PodDisruptionBudget (PDB) - 74%</strong> of charts do not define a PDB. This is another high-impact gap: roughly only one in four charts includes a PodDisruptionBudget. Without a PDB, there's no built-in protection against voluntary disruptions.</p>
<ul>
<li>The fact that most charts omit this means they are prone to downtime during routine operations like node rotation or cluster upgrades, unless the user manually adds a PDB.</li>
</ul>
</li>
<li><p><strong>CPU Limits - 63%</strong> of charts have no CPU limits on containers. Nearly two-thirds of charts do not cap CPU usage. While Kubernetes can still function without limits, the risk is that a container under heavy load could consume all CPU cycles on a node.</p>
<ul>
<li>This can cause <em>noisy neighbor</em> issues and even lead to other critical pods getting starved. The audit shows many charts leave this unchecked.</li>
</ul>
</li>
<li><p><strong>Memory Limits - 60%</strong> of charts lack memory limits. Similar to CPU limits, a significant portion don't set any max memory usage.</p>
<ul>
<li>Without memory limits, a memory leak or spike in one container can trigger an OutOfMemory condition on the node, potentially killing not just that container but others on the node as well. Memory limits contain the impact of such issues to the offending pod. The lack of limits in 60% of charts suggests a prevalent oversight, possibly because setting a one-size-fits-all memory limit is tricky and maintainers opt not to set any - but at the cost of reliability.</li>
</ul>
</li>
<li><p><strong>CPU Requests - 51%</strong> of charts do not declare CPU requests. About half of the charts don't reserve CPU for their pods.</p>
<ul>
<li>This means the scheduler doesn't account for their CPU needs explicitly, which can lead to packing too many CPU-intensive pods on a node. Not having CPU requests can also degrade the effectiveness of autoscaling (HPA) because the HPA's decisions often rely on knowing the CPU utilization relative to requests. The fact that ~49% do set CPU requests is a mildly positive sign.</li>
</ul>
</li>
<li><p><strong>Memory Requests - 49%</strong> of charts have no memory requests. This is in roughly the same range as CPU requests (just a hair better). About half the charts don't reserve memory.</p>
<ul>
<li>Without memory requests, the scheduler might place too many memory-hungry pods together. However, the other ~51% do set memory requests, which indicates that at least for half the charts, basic resource reservations are considered.</li>
</ul>
</li>
<li><p><strong>Liveness Probes - 20%</strong> of charts lack a liveness probe. Here we see a much better adoption: 80% include liveness probes.</p>
<ul>
<li>This is encouraging, it suggests that the majority of chart maintainers recognize the importance of self-healing for their applications. The 20% missing probes might be either very simple apps that don't need it (though almost every app benefits from a liveness check) or just oversights.</li>
</ul>
</li>
<li><p><strong>Readiness Probes - 15%</strong> of charts lack a readiness probe. This was the most well-adopted criterion: about 85% of charts have readiness probes configured.</p>
<ul>
<li><p>Many chart authors seem to prioritize this, as it directly affects user experience during deployments/updates.</p>
</li>
<li><p>Readiness Probes - 15% of charts lack a readiness probe. This was the most well‑adopted criterion: about 85% of charts have</p>
</li>
<li><p><strong>Note:</strong> <em>a portion of the remaining ~15% may not serve traffic directly (e.g., agents/Daemons without a Service, batch/cron jobs), so a readiness check may not be necessary for those workloads.</em></p>
</li>
</ul>
</li>
<li><p><strong>PriorityClass - 15%</strong> do not specify any PriorityClass (thus pods run at default priority). This criterion is a bit different from others because not every app truly needs a custom priority; it's more relevant for multi-tenant clusters or ensuring system-critical pods have higher priority.</p>
<ul>
<li>The low adoption isn't as alarming as the others - it likely reflects that most charts use the default priority (which is fine for many cases). The 15% that do set a PriorityClass are usually charts for important infrastructure components (like ingress controllers, logging agents, etc.) where maintainers deemed it necessary to ensure those pods are less likely to be evicted or preempted.</li>
</ul>
</li>
</ul>
<p>In summary, the <strong>most commonly missing features</strong> were <strong>topology spread constraints, PodDisruptionBudgets, and autoscaling</strong>, each absent in well over 70% of charts. On the flip side, <strong>readiness and liveness probes</strong> were well-adopted by ~4 out of 5 charts, indicating that basic health monitoring is largely in place. Resource requests/limits showed a mixed picture - about half the charts enforce them, half don't.</p>
<p>It's worth noting that some charts might intentionally omit certain measures/settings expecting the user to configure them (for example, an autoscaler might be left out if the application's scaling requirements vary widely between deployments). However, given Helm charts often aim to provide a reasonable default setup, it's generally better to include these reliability features disabled or set to sensible defaults (which users can override) than to leave them out entirely.</p>
<p>These findings highlight areas where chart maintainers could improve:</p>
<ul>
<li><p><strong>Implementing PodDisruptionBudgets</strong> would greatly enhance resilience during cluster maintenance.</p>
</li>
<li><p><strong>Adding Topology Spread Constraints</strong> (even a simple zone spread) would add high availability for multi-node deployments.</p>
</li>
<li><p><strong>Including an HPA</strong> (even off by default but available) would encourage autoscaling usage; setting minReplicas ≥ 2 under HPA provides redundancy.</p>
</li>
<li><p><strong>Setting resource requests/limits</strong> (perhaps conservative defaults) would promote more consistent performance and avoid resource contention issues[6].</p>
</li>
<li><p>Exposing these controls as configurable values (with sensible defaults) raises the reliability baseline of the Helm ecosystem with minimal friction.</p>
</li>
</ul>
<h2 id="heading-reliability-by-application-category"><strong>Reliability by Application Category</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286524919/3a8ccd6e-5b72-4343-9a27-6c52dd8999a9.png" alt class="image--center mx-auto" /></p>
<p>We grouped the charts into broad categories (based on the primary domain or function of the application) to see if certain types of applications tend to be more reliably configured than others. The categories included <strong>Monitoring/Logging</strong>, <strong>Security</strong>, <strong>Networking</strong>, <strong>Database</strong>, <strong>Storage</strong>, <strong>Streaming/Messaging</strong>, <strong>Integration/Delivery (CI/CD)</strong>, <strong>AI/Machine Learning</strong>, and a few <strong>Uncategorized</strong> (for charts that didn't clearly fit a single domain).</p>
<p>There were some noticeable differences in average scores across these groups:</p>
<ul>
<li><p><strong>Streaming &amp; Messaging</strong> - Charts in this category (e.g. Apache Kafka, Pulsar, RabbitMQ) had the <em>highest average reliability score</em>, around <strong>5.3/10</strong>. This was the only category averaging above 5. A likely reason is that streaming systems are often stateful and critical, so their charts (especially Kafka's and Pulsar's) tend to incorporate features like PDBs and resource settings.</p>
</li>
<li><p><strong>Databases</strong> - Database charts (for systems like MySQL, PostgreSQL, MongoDB, etc.) also scored relatively well, averaging about <strong>4.4/10</strong>. This was among the higher averages. Databases are stateful and often require careful handling of downtime, so we saw that many database charts include things like PDBs and requests/limits.</p>
</li>
<li><p><strong>Integration/CI-CD</strong> - This category (which includes things like Argo CD, Jenkins, GitLab Runner, etc.) had a moderate-to-high average around <strong>4.2/10</strong>. It's a small sample size, but notably charts like <strong>GitLab</strong> and <strong>Harbor</strong> (artifact registry, which we placed under integration/delivery) had decent scores (Harbor was 7, GitLab 7).</p>
</li>
<li><p><strong>AI / Machine Learning</strong> - This is an interesting category. We grouped various machine learning tool charts (like Kubeflow, MLFlow, etc.) here. The average was roughly <strong>4.0/10</strong>, about on par with the global average. We had a mix: <strong>Kubeflow's official chart</strong> scored 8 (very good), but some others like smaller ML tools scored low.</p>
</li>
<li><p><strong>Networking</strong> - Charts providing networking infrastructure (e.g. ingress controllers like NGINX, CNI plugins like Calico, service meshes, etc.) averaged around <strong>3.9/10</strong>. This is just below the overall average. Many networking-related charts turned out to be missing a number of best practices. It's somewhat surprising because one would expect networking components to be critical; the low scores might be because some networking daemons run as DaemonSets or have non-standard setups that our criteria didn't fully apply to (or were just not configured with those features).</p>
</li>
<li><p><strong>Security</strong> - Charts for security tools (like Falco, cert-manager, external-secrets, etc.) averaged roughly <strong>3.7/10</strong>. This was on the lower side. Notably, <strong>Falco's chart scored 0</strong> (it lacked all the features), which is a big red flag since Falco itself is a tool for security monitoring. This suggests reliability configuration hasn't been a focus in some security tool charts, perhaps they assume a skilled operator will deploy and tune them, or just oversight.</p>
</li>
<li><p><strong>Storage</strong> - Storage system charts (e.g. Longhorn, OpenEBS, MinIO, etc.) were also below average, at around <strong>3.6/10</strong>. It's somewhat concerning because storage systems are stateful and critical; one might hope their charts are highly robust.</p>
</li>
<li><p><strong>Monitoring &amp; Logging</strong> - This was the <strong>lowest-scoring category</strong>, averaging about <strong>3.36/10</strong>. It also had the largest number of charts (since there are many monitoring/logging tools). A significant number of charts here had poor scores. <strong>Grafana Loki</strong>, however, was an outlier with a 9 (which helped a bit). It's possible maintainers assume these tools run with a certain redundancy externally, or they simply haven't prioritized the reliability of the monitoring system itself. The irony is that tools used to monitor reliability of other apps were themselves often not configured reliably by default.</p>
</li>
<li><p><strong>Uncategorized</strong> - We had a small set of charts we labeled uncategorized (miscellaneous). Their average was around <strong>5.1/10</strong>, interestingly high. This bucket included things like some operator frameworks or bundles that didn't fit elsewhere.</p>
</li>
</ul>
<p>Overall, these category-based observations indicate that <strong>stateful services (databases, streaming)</strong> tend to have better reliability setups than many <strong>operational or add-on tools (monitoring, security)</strong>. One reason could be that stateful applications <em>demand</em> careful handling (you can't just casually restart a database without thinking of data consistency, etc.), so chart authors had to incorporate protections like PDBs. Meanwhile, things like metric collectors or log shippers, while also important, might be seen as easier to redeploy and thus chart authors were less strict about adding budgets or spreads.</p>
<p>These differences highlight that if you are deploying certain types of applications, you should be especially vigilant. For example, if you deploy a <strong>monitoring stack</strong>, double-check its chart for missing reliability configs (our data suggests it's likely missing a few).</p>
<p>In short, while no category was perfect, <strong>some domains clearly lag in reliability configuration</strong> (monitoring/logging and some infra tools), and users should plan to fortify those charts themselves.</p>
<h2 id="heading-top-performing-charts-examples-of-good-practice"><strong>Top Performing Charts (Examples of Good Practice)</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286536597/82a6c1a5-61c3-4192-8d9a-d1990e78a756.png" alt class="image--center mx-auto" /></p>
<p>Despite the generally low scores overall, we identified a set of charts that serve as <strong>positive examples</strong> of how to package an application for reliability. These top performers managed to include most of the recommended best practices. Here are a few notable ones:</p>
<ul>
<li><p><strong>Grafana Loki</strong> - <strong>Score: 9/10.</strong> This was the highest scoring chart in our audit. Loki (a log aggregation system) had all but one of the criteria present. It defined resource requests/limits, had both probes, included an HPA, set a PodDisruptionBudget, and even topology spread constraints.</p>
</li>
<li><p><strong>Apache Kafka</strong> - <strong>Score: 8/10.</strong> Kafka is a critical streaming platform and its Helm chart scored very well. Included PDBs for brokers, resource requests/limits, and liveness/readiness probes.</p>
</li>
<li><p><strong>Keycloak</strong> - <strong>Score: 8/10.</strong> Keycloak (an identity management service) also was configured with many best practices. It had health probes, resource management, PDB, etc.</p>
</li>
<li><p><strong>Pulsar</strong> - <strong>Score: 8/10.</strong> Apache Pulsar, another streaming platform, did excellently as well. Similar to Kafka, its chart includes comprehensive settings. The Pulsar chart actually consists of multiple components (broker, zookeeper, bookkeeper), each handled carefully with appropriate configs.</p>
</li>
<li><p><strong>Kubeflow</strong> - <strong>Score: 8/10.</strong> Kubeflow (the machine learning toolkit) had an official chart that scored high. This is interesting because Kubeflow is a very complex system. Multiple services configured with PDBs, resource requests/limits, and liveness/readiness probes; HPA is supported on components that can scale.</p>
</li>
<li><p><strong>Sentry</strong> - <strong>Score: 8/10.</strong> Sentry (error tracking platform) also was among the top. Sentry being an operational tool that teams rely on, it's good that its helm chart tries to keep it highly available (for example, ensuring the web and worker pods have proper probes and budgets).</p>
</li>
<li><p><strong>GitLab</strong> - <strong>Score: 7/10.</strong> GitLab's chart (particularly the omnibus or the cloud-native GitLab chart) scored in the reliable tier as well. Given the number of sub‑components, this reflects broad coverage of probes, resource controls, and PDBs, with two criteria not satisfied in our scoring.</p>
</li>
<li><p><strong>OpenEBS</strong> - <strong>Score: 7/10.</strong> OpenEBS (a storage orchestrator) was a bright spot in the storage category, scoring 7. It Included PDBs (important for data pods) and resource controls; a stronger showing within the storage category. It stands in contrast to Longhorn's chart (which scored 0), showing not all storage projects neglect reliability.</p>
</li>
<li><p><strong>Harbor</strong> - <strong>Score: 7/10.</strong> Harbor (container registry) is another complex application that scored well. PDBs and resource settings were present across core components (database, core, job service, etc.).</p>
</li>
</ul>
<p>These top charts illustrate that <strong>high reliability scores are achievable</strong>. They typically come from either: well-known companies/communities that enforce good devops practices in their charts (e.g., Grafana on Loki), or inherently critical software whose maintainers know the users will demand a resilient setup (databases, security/auth services, etc.).</p>
<h2 id="heading-poorest-scoring-charts"><strong>Poorest Scoring Charts</strong></h2>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286545972/c1f5f036-42ce-4f7e-999c-eecb6e325b32.png" alt class="image--center mx-auto" /></p>
<p>On the other end of the spectrum, we saw quite a few charts with minimal or no reliability features. It's important to highlight some of these <strong>not to single them out for blame, but to illustrate common patterns of omission</strong> and to caution users of these charts to take extra care. Here are a few of the lowest-scoring examples:</p>
<ul>
<li><p><strong>Falco</strong> - <strong>Score: 0.</strong> Falco is a popular security monitoring tool (runtime security). Shockingly, its Helm chart did not include any of the checked reliability configurations. Users of Falco should be aware that they might need to add their own reliability settings. It's a classic case where perhaps the focus was on the security functionality of the app, and the chart packaging received less attention to reliability.</p>
<ul>
<li><strong>Note:</strong> Deploys as a DaemonSet by default; PDB/TopologySpread/HPA/Replicas are N/A.</li>
</ul>
</li>
<li><p><strong>Longhorn</strong> - <strong>Score: 0.</strong> Longhorn is a cloud-native distributed storage solution. A zero score here is concerning because storage systems are complex and not having (for example) a PodDisruptionBudget for the storage pods could lead to data unavailability during maintenance.</p>
<ul>
<li><strong>Note:</strong> Mixed workloads (Deployments/StatefulSets/DaemonSets). DS components won't use PDB/Spread/HPA;</li>
</ul>
</li>
<li><p><strong>Fluent Bit</strong> - <strong>Score: 0.</strong> Fluent Bit is a log forwarding agent. Its chart scoring 0 indicates it likely runs as a DaemonSet with no added frills. Logging pipelines are critical for SRE observability, so keeping them reliable is important.</p>
<ul>
<li><strong>Note</strong>: Deploys as a DaemonSet by default; PDB/TopologySpread/HPA/Replicas are N/A.</li>
</ul>
</li>
<li><p><strong>Calico (Tigera Operator)</strong> - <strong>Score: 0.</strong> Calico is a networking CNI for Kubernetes, and it often runs via an operator.</p>
</li>
<li><p><strong>Grafana Alloy</strong> - <strong>Score: 0.</strong> Grafana "Alloy" is a lesser-known component (possibly a plugin or sidecar). It scoring 0 again emphasizes that even within a known vendor's ecosystem, not every chart is equal - Loki's was excellent, but this one was not.</p>
<ul>
<li>Note: Typically runs as a DaemonSet for node telemetry; apply DS caveats (PDB/TopologySpread/HPA/Replicas are N/A).</li>
</ul>
</li>
<li><p><strong>Prometheus Node Exporter</strong> - <strong>Score: 0.</strong> The node-exporter chart (listed as part of prometheus-community) also had none of the reliability features. Node-exporter runs as a DaemonSet on each node to collect metrics. Similar to Fluent Bit, running as DaemonSet might have led maintainers to not include budgets or autoscaling (since those don't apply the same way)</p>
<ul>
<li>Note: Deploys as a DaemonSet by default; PDB/TopologySpread/HPA/Replicas are N/A.</li>
</ul>
</li>
<li><p><strong>Actions Runner Controller</strong> - <strong>Score: 0.</strong> This is a chart for a GitHub Actions self-hosted runner controller. It scoring 0 means it lacks any reliability config; as an operator-like component, it probably wasn't given PDBs or special priority.</p>
</li>
<li><p><strong>AMD GPU and Intel GPU plugins</strong> - <strong>Score: 0.</strong> We saw charts for GPU device plugins (for AMD and Intel GPUs) also with zero scores. These are deployed as DaemonSets to advertise GPUs to the cluster. They had no reliability features in charts, which might be because they're expected to be super lightweight.</p>
<ul>
<li>Note: Deploys as a DaemonSet by default; PDB/TopologySpread/HPA/Replicas are N/A.</li>
</ul>
</li>
</ul>
<p>In total, we had <strong>10 charts with 0 score</strong> (some we described above). Many others were just slightly above 0 (score 1 or 2).</p>
<p>Common patterns among low-scoring charts:</p>
<ol>
<li><p><strong>Many are infrastructure add-ons (operators, agents, plugins)</strong> rather than end-user applications. It seems chart maintainers for these system-level tools often keep the chart minimal.</p>
</li>
<li><p><strong>DaemonSet workloads --</strong> Several 0‑score charts are DaemonSets (e.g., Fluent Bit, node‑exporter, GPU plugins). For DS, controls like PDB/TopologySpread/HPA/Replicas are generally not applicable; what matters is CPU/Memory requests and limits, Liveness probes, PriorityClass, and DS rollingUpdate settings.</p>
</li>
<li><p><strong>Relatively newer or niche projects</strong> - Some low performers are not as mature or widely used, perhaps, so their charts haven't undergone rigorous production-hardening by the community.</p>
</li>
</ol>
<p>For users, the takeaway is:</p>
<p><strong>if you are using one of these low-scoring charts (or any chart that hasn't clearly advertised its reliability features), do not deploy it blindly in production.</strong></p>
<p>At a minimum, consider:</p>
<p>- Checking carefully the values to define PodDisruptionBudget, Topology Spread Constraint and HPA wherever applicable.</p>
<p>- Setting resource requests/limits via values overrides.</p>
<p>- Adding an HPA (if the app would benefit from scaling).</p>
<p>- Ensuring you attach liveness/readiness probes (maybe via chart values or a side patch if not supported natively).</p>
<p>- If it's a critical infrastructure component, possibly assign it a PriorityClass to avoid eviction (for example, set it to the system-cluster-critical priority if appropriate, or create a custom one).</p>
<p>Basically, use the findings here as a checklist against any Helm chart you deploy: check if it has these items, and if not, you might need to supply them.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286557924/c4b687f9-3bb5-46e2-80f7-e8f1c9f5ca99.png" alt class="image--center mx-auto" /></p>
<h2 id="heading-conclusion-and-recommendations"><strong>Conclusion and Recommendations</strong></h2>
<p>This reliability audit of Helm charts has revealed a sizable gap between the reliability best practices that we <em>know</em> are important and what is actually implemented in many Helm charts today. While a few charts exemplify excellence in configuration, the majority have significant room for improvement. At the same time, we acknowledge that different use cases require different safeguards.</p>
<p>In closing, we summarize recommendations for both <strong>chart users (operators)</strong> and <strong>Helm chart maintainers</strong> and to act on these insights, and how tools like Preq/Prequel can assist in catching unmitigated risks.</p>
<p><strong>For Chart Maintainers:</strong></p>
<ul>
<li><p><strong>Embed Reliability Best Practices by Default:</strong> If you maintain a Helm chart, consider this an encouragement to bake in more of these features. These should be part of the "standard equipment" of your chart.</p>
</li>
<li><p><strong>Provide Autoscaling Options:</strong> Where applicable, provide an HPA in the chart (it can be off by default, but ready to enable). This signals to users that your application supports scaling and encourages them to use it.</p>
</li>
<li><p><strong>Don't Skimp on Probes:</strong> Ensure every long-running pod has a liveness and readiness probe defined. This is one area many charts did well, and all should. It significantly increases resiliency</p>
</li>
<li><p><strong>Set Resource Requests/Limits:</strong> We recognize that picking default resource values can be tricky (since workloads differ), but providing reasonable defaults is better than none.</p>
</li>
<li><p><strong>Use PriorityClass for Critical Components:</strong> If your chart is for a system-critical service (operators, controllers, ingress, etc.), consider assigning a high PriorityClass (or at least make it configurable).</p>
</li>
<li><p><strong>Test Disruption Scenarios:</strong> As a maintainer, test how your chart behaves during common scenarios: node drains, upgrades (in case of stateful applications if someone does helm upgrade, do all pods restart at once?), high load (does CPU spike and if so, is HPA there to help?), etc. This experiential testing can highlight missing pieces.</p>
</li>
<li><p><strong>Leverage Community Standards:</strong> The Kubernetes community (and projects like the CNCF) often provide guidelines or even boilerplate for these configurations. Following these guides can serve as a checklist for your chart.</p>
</li>
<li><p><strong>Document appropriately:</strong> Clear and comprehensive documentation is essential for helping end-users configure reliability settings that align with their specific needs and operational constraints. Good documentation not only enhances the experience for maintainers but also ensures a smooth experience for end-users.</p>
</li>
</ul>
<p><strong>For Helm Chart Users (Deployers):</strong></p>
<ul>
<li><p><strong>Review Charts Before Production Use:</strong> Do not assume a Helm chart is production-ready. As this audit shows, many are not, in terms of reliability. Before deploying, <strong>audit the chart's values and manifests</strong> yourself.</p>
</li>
<li><p><strong>Override and Augment Configurations:</strong> The beauty of Helm is you can supply custom values. Use this to your advantage.</p>
</li>
<li><p>Consider writing an <strong>overlay chart or a wrapper</strong> that adds missing pieces.</p>
<ul>
<li><strong>Note:</strong> <em>overlays/wrappers break the "least knowledge" principle. You can't rely solely on upstream SemVer/upgrade notes. Treat it like a maintained fork.</em></li>
</ul>
</li>
<li><p><strong>Contribute Back Improvements:</strong> If you as a user had to add reliability configs to make a chart stable, consider contributing that back to the chart's repository (submit a pull request or issue). Prefer upstreaming first; use overlays only when upstream changes are not feasible in the short term.</p>
</li>
<li><p><strong>Use Detection Tools:</strong> Consider using tools that can scan your cluster or manifests for missing best practices, essentially doing what this audit did, but for your environment. Tools like Prequel (start for free) can be integrated into CI pipelines or run against your Helm releases continuously to flag if, say, a new deployment is missing a liveness probe or PDB. In an enterprise setting, Prequel could be set up as a guardrail: whenever a new chart is deployed, it checks the CRE rules and alerts if something critical is absent. This kind of automation ensures that even if a maintainer hasn’t provided a feature, you catch it before it causes an incident.</p>
</li>
</ul>
<p><strong>The Role of Continuous Reliability Scanning:</strong> Finally, it's worth re-emphasizing the value of continuous monitoring using tools like Prequel. Just as security scanning of images and CVEs has become a standard part of DevOps, <strong>reliability scanning is emerging as a complementary practice</strong>. By leveraging the <a target="_blank" href="https://docs.prequel.dev/cres/commercial">[CRE rule set]</a> (which encapsulates knowledge of failure patterns), teams can detect misconfigurations early.</p>
<p><a target="_blank" href="https://www.prequel.dev/sign-up"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1762286591051/5e7dde61-ae60-4d3b-8ac8-ba01b833f60f.png" alt class="image--center mx-auto" /></a></p>
<p>The journey to reliable Kubernetes deployments is a shared responsibility between chart creators and users. Helm charts are a powerful vehicle for distributing applications, but they should carry not just the app itself, but also the wisdom of running it reliably. Our research is designed to bring awareness to the risk so that teams can fully embrace that philosophy. By implementing the recommendations above, we can collectively raise the reliability bar.</p>
<hr />
<p><a target="_blank" href="https://docs.prequel.dev/">[1] Prequel Documentation‍</a></p>
<p><a target="_blank" href="https://dev.to/cloud-sky-ops/post-210-reliability-by-design-probes-poddisruptionbudgets-and-topology-spread-constraints-473d">[2] [3] [4] [7] Post 2/10 — Reliability by Design: Probes, PodDisruptionBudgets, and Topology Spread Constraints - DEV Community‍</a> <a target="_blank" href="https://kubernetes.io/docs/concepts/services-networking/">[5] Services, Load Balancing, and Networking‍</a></p>
<p><a target="_blank" href="https://kubernetes.io/docs/concepts/services-networking/">[6] [8] Kubernetes Best Practices for Reliability‍</a></p>
<p><a target="_blank" href="https://cloud.ibm.com/docs/openshift?topic=openshift-pod_priority">[9] IBM Cloud Docs‍</a></p>
<p><a target="_blank" href="https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/">[10] Horizontal Pod Autoscaling | Kubernetes</a></p>
]]></content:encoded></item><item><title><![CDATA[Community: The 100% Open-Source AI Stack That Automates My Business, and Tricks for Troubleshooting It]]></title><description><![CDATA[Most teams don't need a full-fledged "AI platform" to automate everyday workflows. You need a reliable way to trigger automation jobs, call a model, keep a little context, and deliver results. That's it.
In this guide I'll show my practical, open-sou...]]></description><link>https://prequel.hashnode.dev/the-100-open-source-ai-stack-that-automates-my-business-and-tricks-for-troubleshooting-it</link><guid isPermaLink="true">https://prequel.hashnode.dev/the-100-open-source-ai-stack-that-automates-my-business-and-tricks-for-troubleshooting-it</guid><category><![CDATA[Open Source]]></category><category><![CDATA[automation]]></category><category><![CDATA[AI]]></category><dc:creator><![CDATA[Lyndon Brown]]></dc:creator><pubDate>Wed, 08 Oct 2025 22:47:03 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1759962854864/fd1f339c-008e-4f6d-b683-aeca1dfb5f3e.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most teams don't need a full-fledged "AI platform" to automate everyday workflows. You need a reliable way to trigger automation jobs, call a model, keep a little context, and deliver results. That's it.</p>
<p>In this guide I'll show my practical, open-source AI stack for automating my business workflows. For me, it was important for my stack to be 100% open source and self-hosted. There are certainly shortcuts you can take with commercial LLMs or other components.</p>
<p>In short, I landed on n8n for orchestration, Ollama for LLM server, and Postgres + pgvector for memory/RAG.</p>
<p>I also developed a simple deployment playbook with k8s extensibility and tips for keeping it reliable and healthy as you go.</p>
<h2 id="heading-why-an-open-source-stack">Why an Open-Source stack</h2>
<p>If you're handling customer data, internal docs, or anything with compliance implications, running locally or on your own cloud removes a ton of uncertainty. With this stack, your prompts, retrieved snippets, and outputs live inside your network, not on somebody else's infrastructure. You can log exactly what you want, keep tokens from leaking, and reason about costs in traditional terms (CPU/RAM/disk) instead of foggy per-token math.</p>
<p>There's also the control aspect. Open tools are swappable. Don't like the model? Pull a different one. Need to move from a laptop to on-prem? Bring your Kubernetes manifests and go. And because these projects are community-driven, you can read the code, file issues, or extend them when you bump into edge cases, no waiting for a vendor.</p>
<p>Oh, yeah, and for me cost mattered here.</p>
<h2 id="heading-a-simple-open-source-ai-stack-that-just-works">A simple open-source AI stack that just works</h2>
<p>At a high level, the flow is straightforward: a trigger fires in n8n (a webhook, a cron, or an event); you fetch context from APIs or files; you optionally search prior knowledge in Postgres + pgvector; you call the model via Ollama; then you save results and push them to Slack, email, the CRM, or a dashboard. That single loop covers a surprising amount of basic business flows like:</p>
<ul>
<li><p>Sending a daily team update</p>
</li>
<li><p>Sorting and replying to customer support requests</p>
</li>
<li><p>Enriching lead details before they go into the CRM</p>
</li>
<li><p>Turning meeting transcripts into notes, or</p>
</li>
<li><p>Answering questions about company policies</p>
</li>
</ul>
<h3 id="heading-why-these-three">Why these three?</h3>
<ul>
<li><p><strong>n8n</strong> gives you a visual, testable pipeline with retries, branching, and a good set of built-in nodes. You can keep 90% of the logic declarative and drop into a "Code" node only where it helps.</p>
</li>
<li><p><strong>Ollama</strong> is one of the most popular low-friction platforms to serve local models: one command to pull, a tiny HTTP API to call. No GPU required for small/quantized models; if you do have one, it'll happily use it.</p>
</li>
<li><p><strong>Postgres + pgvector</strong> turns your database into a memory store. You can keep workflow state, results, and embeddings in one place, with real indexing and backups, no extra vector service to run.</p>
</li>
</ul>
<h3 id="heading-do-you-really-need-langchain-autogpt-vllm">Do you really need LangChain / AutoGPT / vLLM?</h3>
<p>These are great AI tools, but you probably don't need them to add value to your workflow on day one.</p>
<ul>
<li><p><strong>LangChain</strong> is great if you're building complex chains, tool routing, or evaluators as a codebase of their own. If your flows are mostly linear ("get data - retrieve context - prompt - send"), n8n's nodes plus a small Code step are usually simpler to reason about and maintain.</p>
</li>
<li><p><strong>AutoGPT</strong> (or other agent frameworks) is useful when the task is genuinely open-ended and needs autonomous planning ("research X, compare Y, produce Z unless blocked"). For business automations, most tasks are bounded: summarize, classify, extract, transform. Agentic loops can add latency and instability you don't need yet.</p>
</li>
<li><p><strong>vLLM</strong> is a fantastic serving stack when throughput, long context, or GPU batching are your constraints. If you're running a handful of concurrent automations, Ollama is much easier operationally.</p>
</li>
</ul>
<p>Rule of thumb: begin with n8n + Ollama + pgvector. If a real bottleneck appears, too many concurrent requests, prompts that need long contexts, or tasks that require autonomous planning then layer on the specialized tool that solves that bottleneck and nothing else.</p>
<h2 id="heading-my-workflow-architecture">My Workflow Architecture</h2>
<p><img src="https://cdn.prod.website-files.com/6610340fef35e74fce0063ed/68e568b95ced728419478cc6_de4e7e75.png" alt /></p>
<p>In practice you'll add a few niceties:</p>
<ul>
<li><p><strong>Keep prompts tidy</strong>: write down a handful of prompt templates you actually use (for summaries, classifications, replies, etc.) and save them in Postgres.</p>
</li>
<li><p><strong>Avoid duplicates</strong>: if you run daily jobs, store a hash of the input. If you've already seen it, skip re-processing. This saves time and avoids sending the same Slack message or email twice.</p>
</li>
<li><p><strong>Log what happens</strong>: after each step, record start time, end time, and status in the database. When something feels slow or fails silently, you'll have a clear history instead of guessing.</p>
</li>
</ul>
<h2 id="heading-run-it-locally-docker-quick-start">Run it locally (Docker Quick Start)</h2>
<p>You can run the stack locally in 10 minutes with Docker. We'll run everything in containers. Postgres + pgvector, n8n, and Ollama, so n8n can call the model at http://ollama:11434 on the internal Docker network.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<ul>
<li><p>Docker Desktop (or Docker Engine) with Compose v2</p>
</li>
<li><p>Optional: psql client for quick DB checks</p>
</li>
</ul>
<h3 id="heading-1-project-layout">1) Project layout</h3>
<pre><code class="lang-bash">mkdir -p ai-stack/{pg-data,n8n-data,init}
<span class="hljs-built_in">cd</span> ai-stack
</code></pre>
<p>Create two files:</p>
<p><strong>docker-compose.yml</strong></p>
<pre><code class="lang-yaml"><span class="hljs-attr">services:</span>
  <span class="hljs-attr">postgres:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">pgvector/pgvector:pg16</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-attr">POSTGRES_USER:</span> <span class="hljs-string">aiuser</span>
      <span class="hljs-attr">POSTGRES_PASSWORD:</span> <span class="hljs-string">supersecret</span>
      <span class="hljs-attr">POSTGRES_DB:</span> <span class="hljs-string">ai</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5432:5432"</span>            <span class="hljs-comment"># change left side if 5432 is busy on host</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./pg-data:/var/lib/postgresql/data</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./init:/docker-entrypoint-initdb.d</span>
    <span class="hljs-attr">healthcheck:</span>
      <span class="hljs-attr">test:</span> [<span class="hljs-string">"CMD-SHELL"</span>,<span class="hljs-string">"pg_isready -U aiuser -d ai"</span>]
      <span class="hljs-attr">interval:</span> <span class="hljs-string">5s</span>
      <span class="hljs-attr">timeout:</span> <span class="hljs-string">5s</span>
      <span class="hljs-attr">retries:</span> <span class="hljs-number">20</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>

  <span class="hljs-attr">n8n:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">n8nio/n8n:latest</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"5678:5678"</span>            <span class="hljs-comment"># change left side if 5678 is busy on host</span>
    <span class="hljs-attr">environment:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DB_TYPE=postgresdb</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DB_POSTGRESDB_HOST=postgres</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DB_POSTGRESDB_PORT=5432</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DB_POSTGRESDB_DATABASE=n8n</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DB_POSTGRESDB_USER=aiuser</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">DB_POSTGRESDB_PASSWORD=supersecret</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">N8N_BASIC_AUTH_ACTIVE=true</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">N8N_BASIC_AUTH_USER=admin@example.com</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">N8N_BASIC_AUTH_PASSWORD=changeme</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">N8N_DIAGNOSTICS_ENABLED=false</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">N8N_RUNNERS_ENABLED=true</span>
    <span class="hljs-attr">depends_on:</span>
      <span class="hljs-attr">postgres:</span>
        <span class="hljs-attr">condition:</span> <span class="hljs-string">service_healthy</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./n8n-data:/home/node/.n8n</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>

  <span class="hljs-attr">ollama:</span>
    <span class="hljs-attr">image:</span> <span class="hljs-string">ollama/ollama:latest</span>
    <span class="hljs-attr">ports:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">"11434:11434"</span>          <span class="hljs-comment"># change left side if 11434 is busy on host</span>
    <span class="hljs-attr">volumes:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-string">./models:/root/.ollama</span> <span class="hljs-comment"># cache models on your disk</span>
    <span class="hljs-attr">healthcheck:</span>
      <span class="hljs-attr">test:</span> [<span class="hljs-string">"CMD"</span>,<span class="hljs-string">"/bin/sh"</span>,<span class="hljs-string">"-c"</span>,<span class="hljs-string">"curl -sf http://localhost:11434/api/tags || exit 1"</span>]
      <span class="hljs-attr">interval:</span> <span class="hljs-string">10s</span>
      <span class="hljs-attr">timeout:</span> <span class="hljs-string">5s</span>
      <span class="hljs-attr">retries:</span> <span class="hljs-number">30</span>
    <span class="hljs-attr">restart:</span> <span class="hljs-string">unless-stopped</span>
</code></pre>
<p><strong>init/00-init.sql</strong></p>
<pre><code class="lang-sql"><span class="hljs-comment">-- DB for n8n to store workflows/executions</span>
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DATABASE</span> n8n <span class="hljs-keyword">WITH</span> OWNER aiuser;

<span class="hljs-comment">-- Enable vector in 'ai' DB and a tiny log table</span>
\connect ai
<span class="hljs-keyword">CREATE</span> EXTENSION <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> vector;

<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> llm_runs (
  <span class="hljs-keyword">id</span> BIGSERIAL PRIMARY <span class="hljs-keyword">KEY</span>,
  <span class="hljs-keyword">prompt</span>     <span class="hljs-built_in">TEXT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  <span class="hljs-keyword">model</span>      <span class="hljs-built_in">TEXT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  response   <span class="hljs-built_in">TEXT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-literal">NULL</span>,
  latency_ms <span class="hljs-built_in">INTEGER</span>,
  created_at TIMESTAMPTZ <span class="hljs-keyword">DEFAULT</span> <span class="hljs-keyword">now</span>()
);
</code></pre>
<p>Bring the stack up:</p>
<pre><code class="lang-bash">docker compose up -d
</code></pre>
<h3 id="heading-2-pull-a-small-model-inside-the-ollama-container">2) Pull a small model (inside the Ollama container)</h3>
<pre><code class="lang-bash">docker <span class="hljs-built_in">exec</span> -it ollama ollama pull llama3.2
</code></pre>
<p>Sanity checks:</p>
<ul>
<li>list models (in container)</li>
</ul>
<pre><code class="lang-bash">docker <span class="hljs-built_in">exec</span> -it ollama curl -s http://localhost:11434/api/tags | jq .
</code></pre>
<ul>
<li>check pgvector is enabled</li>
</ul>
<pre><code class="lang-bash">psql -h localhost -U aiuser -d ai -c <span class="hljs-string">"SELECT extname FROM pg_extension;"</span>
</code></pre>
<p>Open n8n at http://localhost:5678. On first visit, you'll see a basic-auth prompt (admin@example.com / changeme), then n8n will ask you to create the Owner account (email/password).</p>
<h2 id="heading-reliability-issues-what-it-breaks-and-how-to-stay-ahead-of-it-quickly">Reliability Issues - what it breaks and how to stay ahead of it quickly</h2>
<p>Self-hosting open source projects definitely comes with its own challenges. You are on the hook to keep it up and running. There is no support team to call.</p>
<p>Here are some of the gotchas I ran into and how I handle them.</p>
<h3 id="heading-tool-reliability-gotchas-amp-fixes">Tool Reliability gotchas &amp; fixes</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Tool</td><td>Issues &amp; Fixes</td></tr>
</thead>
<tbody>
<tr>
<td><strong>n8n</strong></td><td><ul><li> Long LLM calls can hit step timeouts which split into smaller steps; add retries with jitter.</li><li> Webhooks may drop chunky payloads so raise body-size limits at ingress/reverse proxy.</li><li> Retries without persistent storage can lose inputs, persist inbound payloads to Postgres first, then process.</li><li> Monitor execution latency and failure rates; limit per-node timeouts sensibly.</li></ul></td></tr>
<tr>
<td><strong>Postgres + pgvector</strong></td><td><ul><li> Queries failing because pgvector not enabled; Run CREATE EXTENSION vector; once per database.</li><li> Vector searches feel slow; Add a vector index (IVFFLAT or HNSW), keep your top-k small (say 5–20), and do routine VACUUM/ANALYZE.</li><li> Too many connections causing random timeout; Add PgBouncer in front of Postgres and keep n8n's pool small.</li></ul></td></tr>
<tr>
<td><strong>Ollama</strong></td><td><ul><li> First-run model pulls are slow/flaky; Pre-pull models on deploy and a tiny warm-up prompt after start</li><li> Runs out of memory on laptops/containers; Use smaller/quantized models, keep prompts short, and give Docker enough RAM/swap.</li><li> Port/DNS weirdness; Remap the host port in Compose file.</li><li> "Model not found" errors; Check /api/tags to see what's loaded, and ollama pull &lt;model&gt; on container startup</li></ul></td></tr>
</tbody>
</table>
</div><h2 id="heading-detect-issues-early-with-community-cres-and-preq">Detect issues early with community CREs (and preq)</h2>
<p>The reliability community has started to maintain a community-driven catalog of failure patterns called CREs(Common Reliability Enumerations) so you don't have to rediscover them in production. Each CRE includes detection as code.</p>
<p>You can run these with preq (pronounced preek), the open source reliability problem detector, to turn noisy logs into clear, actionable signals.</p>
<p>The public catalog covers dozens of popular technologies, from Kubernetes and databases to application runtimes. Here are a few relevant ones my AI stack or similar ones:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>CRE</td><td>Technology</td><td>What it detects</td><td>Quick mitigation</td></tr>
</thead>
<tbody>
<tr>
<td>CRE-2025-0179</td><td>n8n</td><td>Items disappear between nodes in long workflows, causing silent data loss and incomplete runs.</td><td>Add item-count checks, enable detailed logging, split long workflows, and use error workflows to capture failures.</td></tr>
<tr>
<td>CRE-2025-0200</td><td>AutoGPT</td><td>AutoGPT loops while debugging itself, consuming tokens and memory until it crashes.</td><td>Detect loops, cap depth and tokens, add circuit breakers, and auto-stop runaway agents.</td></tr>
<tr>
<td>CRE-2025-0137</td><td>Kubernetes Runtime</td><td>A pod exceeds its memory limit and is killed, often showing up as CrashLoopBackOff.</td><td>Increase memory limits, profile for leaks, tune heap/GC, use VPA, and add memory alerts.</td></tr>
<tr>
<td>CRE-2025-0071</td><td>Kubernetes</td><td>CoreDNS has no healthy pods, leading to cluster-wide DNS failures.</td><td>Check pods and logs, scale replicas, restart rollout, and confirm kube-dns endpoints.</td></tr>
<tr>
<td>CRE-2025-0077</td><td>Postgres</td><td>Postgres cannot extend files because the disk is full, blocking new writes.</td><td>Free space, clean old data, run vacuum, expand disk size, and set up disk usage alerts.</td></tr>
</tbody>
</table>
</div><p>You can wire detections to Slack, email, or even Jira with a short runbook ("what it means" and "what to do") to make fixes faster.</p>
<p>If you are setting up this stack, or your own, set aside 10 minutes to <a target="_blank" href="https://docs.prequel.dev/install">download preq and run it</a>. It's open source, and it will save you from the dreaded "why did this silently fail?" mornings. Begin with the n8n data-loss rule, a basic Kubernetes exit code/DNS rule if you are running clusters, and a Postgres disk or connections check. You can always add more as your workflows grow.</p>
<p>👉 Explore the full <a target="_blank" href="https://github.com/prequel-dev/cre">CRE catalog</a>; try out <a target="_blank" href="https://github.com/prequel-dev/preq">preq</a>, and if you find it useful, don't forget to ⭐ the repo to support the community. : )</p>
<h2 id="heading-references">References</h2>
<ul>
<li><p>n8n – docs: <a target="_blank" href="https://n8n.io/docs">https://n8n.io/docs</a></p>
</li>
<li><p>Ollama – repo: <a target="_blank" href="https://github.com/ollama/ollama">https://github.com/ollama/ollama</a></p>
</li>
<li><p>Postgres + pgvector – <a target="_blank" href="https://github.com/pgvector/pgvector">https://github.com/pgvector/pgvector</a></p>
</li>
<li><p>Kubernetes – <a target="_blank" href="https://kubernetes.io/docs/home/">https://kubernetes.io/docs/home/</a></p>
</li>
<li><p>CREs (Common Reliability Enumerations) – <a target="_blank" href="https://github.com/prequel-dev/cre">https://github.com/prequel-dev/cre</a></p>
</li>
<li><p>Preq (run CREs) – <a target="_blank" href="https://github.com/prequel-dev/preq">https://github.com/prequel-dev/preq</a></p>
</li>
</ul>
]]></content:encoded></item><item><title><![CDATA[How I find and fix Kubernetes Exit Codes and Misconfigurations for free]]></title><description><![CDATA[Kubernetes is powerful, but troubleshooting issues in a live cluster can be painful. In a complex deployment, critical warning signs often hide in thousands of log lines and events. What if we could surface these reliability issues before they take a...]]></description><link>https://prequel.hashnode.dev/how-i-find-and-fix-kubernetes-exit-codes-and-misconfigurations-for-free</link><guid isPermaLink="true">https://prequel.hashnode.dev/how-i-find-and-fix-kubernetes-exit-codes-and-misconfigurations-for-free</guid><category><![CDATA[Kubernetes]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Reliability]]></category><category><![CDATA[Devops]]></category><dc:creator><![CDATA[Lyndon Brown]]></dc:creator><pubDate>Fri, 12 Sep 2025 15:23:19 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757690109283/432e035a-d3d8-46e1-982c-2af7df5546de.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Kubernetes is powerful, but troubleshooting issues in a live cluster can be painful. In a complex deployment, critical warning signs often hide in thousands of log lines and events. What if we could surface these reliability issues <strong>before</strong> they take applications down?</p>
<p><strong>Preq</strong> (pronounced “preek”) is an open-source tool that brings a proactive approach to Kubernetes troubleshooting. It is a reliability problem detector that checks your cluster’s logs, events, and configurations against a community-driven catalog of failure patterns [1]. Using Preq, you can monitor your cluster and catch misconfigurations, anti-patterns, or <strong>bugs</strong> early, instead of discovering them during a 2 AM incident [1].</p>
<h2 id="heading-installing-preq-via-krew"><strong>Installing preq via Krew</strong></h2>
<p><a target="_blank" href="https://docs.prequel.dev/"><strong>preq</strong></a> is distributed as a kubectl plugin, making it easy to install through the Kubernetes Krew plugin manager. First, ensure you have Krew set up (if not, install it from the <a target="_blank" href="https://krew.sigs.k8s.io/docs/user-guide/setup/install/">official docs</a>). Then install Preq with a single command:</p>
<table><tbody><tr><td><p><strong>kubectl krew install preq</strong></p></td></tr></tbody></table>

<p>Within seconds, the plugin is ready to use[1]. There’s no extra configuration needed. Preq ships with the latest common reliability enumeration (CRE) rule packages baked in. It auto-updates its rules so you’re always scanning for the newest issues.</p>
<h2 id="heading-running-kubectl-preq-from-the-cli"><strong>Running Kubectl preq from the CLI</strong></h2>
<p>Once installed, you can run Preq directly via kubectl to check various Kubernetes resources and their logs:</p>
<ul>
<li><p><strong>Pods:</strong> Scan an individual pod’s logs and related events. For example, <strong>kubectl preq my-pod-abc123</strong> will fetch that pod’s logs and events, then compare them against the CRE rule library. [1]</p>
</li>
<li><p><strong>Services:</strong> Running <strong>kubectl preq service/my-service</strong> triggers Preq to assess the pods behind that Service. While Services themselves don’t have logs, Preq will identify the endpoints/pods for the service and check their logs and events for known issues.</p>
</li>
<li><p><strong>Jobs and CronJobs:</strong> Run Preq on a Job or on pods created by a CronJob to inspect execution logs and events[12].</p>
</li>
</ul>
<p>Under the hood, the Preq plugin uses Kubernetes APIs. This means you can run Preq on any resource type that has associated logs or events, giving you a flexible “detective” for your cluster.</p>
<h3 id="heading-using-preq-with-configmaps-and-events"><strong>Using Preq with ConfigMaps and Events</strong></h3>
<p>The current release of Preq primarily targets logs and manifests, but you can also leverage it for configuration files and cluster events with a little creativity.</p>
<ul>
<li><p><strong>ConfigMaps</strong></p>
<ul>
<li>Directly scan a ConfigMap with the plugin:</li>
</ul>
</li>
</ul>
<table><tbody><tr><td><p>kubectl preq -n &lt;namespace&gt; configmap/&lt;name-of-config-map&gt;</p></td></tr></tbody></table>

<ul>
<li><p><strong>Kubernetes events</strong></p>
<ul>
<li>Use this feeder to stream a timestamp and the raw event into Preq:</li>
</ul>
</li>
</ul>
<table><tbody><tr><td><p>kubectl get events -A -o json | jq -r '.items[] | "(.metadata.creationTimestamp) (tojson)"' | kubectl preq</p></td></tr></tbody></table>

<ul>
<li><p><strong>Other workload configurations beyond ConfigMaps</strong></p>
<ul>
<li>Use this workaround to feed deployments and similar manifests as compact JSON, stamped with a single UTC timestamp per line:</li>
</ul>
</li>
</ul>
<table><tbody><tr><td><p>kubectl get deploy -A -o json | jq -c . | sed -e "1s/^/$(date -u +"%Y-%m-%dT%H:%M:%SZ") /" | kubectl preq</p></td></tr></tbody></table>

<h2 id="heading-example-cres"><strong>Example CREs</strong></h2>
<p>We’ll highlight a few Common Reliability Enumerations created  by community members[2][3][4][5]:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CRE</strong></td><td><strong>What breaks</strong></td><td><strong>Signals you will see</strong></td></tr>
</thead>
<tbody>
<tr>
<td><a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0119">CRE-2025-0119</a></td><td>Too many pods down during an update</td><td>Rollout stalls, unavailable replicas, PDB budget exceeded</td></tr>
<tr>
<td><a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0071">CRE-2025-0071</a></td><td>Cluster DNS resolution fails when CoreDNS has no ready pods or endpoints</td><td>CoreDNS availableReplicas at zero, kube dns endpoints empty, pods in CrashLoopBackOff, CoreDNS logs show errors</td></tr>
<tr>
<td><a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0048">CRE-2025-0048</a></td><td>Worker node enters NotReady because control plane cannot resolve the node’s FQDN</td><td>Node status shows NotReady without resource pressure, control plane logs may show hostname resolution errors</td></tr>
<tr>
<td><a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0125">CRE-2025-0125</a></td><td>Kubelet crashes under rapid pod launches causing node NotReady and full node level outage with pod evictions</td><td>Node NotReady, mass pod evictions and rescheduling, kubelet logs show panic in EventedPLEG evented.go</td></tr>
</tbody>
</table>
</div><h2 id="heading-exit-code-cres-crashes-and-their-causes-137-127-134-139"><strong>Exit Code CREs: Crashes and Their Causes (137, 127, 134, 139)</strong></h2>
<p>Now let’s talk about a different kind of problem: when your containers keep exiting with mysterious status codes. Preq includes CRE rules[7] for common exit codes to help pinpoint why a container crashed. Let’s break down the usual suspects:</p>
<p><strong>Exit Code 137</strong> – This typically means the process was killed with <strong>SIGKILL</strong>, which in Kubernetes often implies an out-of-memory kill. In other words, the container was using more memory than allowed, so the OS OOM killer terminated it[6][7]. It can also happen if someone manually kill -9 the process, but OOM is the usual cause. In Kubernetes you’ll often see “Reason: OOMKilled” in the pod’s status if this is the case.</p>
<ul>
<li><ul>
<li><p><strong>Why it happens:</strong> Your app exceeded its memory limit or the node ran out of memory.</p>
<ul>
<li><strong>What to do:</strong> Check the container’s memory limits and usage. You can run kubectl top pod to see if it was using a lot of memory. Increasing the memory limit (or request) for the container can prevent the OOMKill, or optimize the application to use less memory. Preq can help by flagging frequent OOM kills so you know to take action before it impacts users.</li>
</ul>
</li>
</ul>
</li>
<li><p><strong>Exit Code 127</strong> – This means <strong>“command not found”</strong>. The process tries to execute a file or command that doesn’t exist in the container’s filesystem [8][9]. It’s a common error when the container’s start command or entrypoint is misconfigured.</p>
<ul>
<li><p><strong>Why it happens:</strong> Either the binary isn’t installed, the path is wrong, or a dependency is missing. It can also be a shell quoting issue or a file permission problem, but usually it’s a missing executable.</p>
</li>
<li><p><strong>What to do:</strong> Describe the pod (kubectl describe pod), often Kubernetes will log a message about “command not found” in the events. Fix the command in your container spec or Dockerfile. Make sure the image has the expected program at the correct location. Preq can catch this by scanning events or termination messages for “exited with code 127” and common error text. The solution is usually straightforward: install the missing tool or correct the command path.</p>
</li>
</ul>
</li>
<li><p><strong>Exit Code 134</strong> – This indicates the process received <strong>SIGABRT</strong> (abort signal)[10]. In plainer terms, the application crashed itself – often due to an internal error like an assertion failure or a call to abort(), or it was terminated after a fatal error.</p>
<ul>
<li><p><strong>Why it happens:</strong> Common causes include bugs (like asserting false or invalid memory access that is caught leading to abort), or sometimes out-of-memory in a different way. Another cause can be hitting a resource limit that triggers an abort.</p>
</li>
<li><p><strong>What to do:</strong> Check the container’s logs for any error messages or stack traces right <strong>before</strong> it exited. Often you’ll see a line about an assertion or fatal error. Preq will highlight the occurrence of a 134 exit and can point out if it’s a known pattern. Ensure you’re not hitting known bugs in the app version, and consider adding liveness probes, if a container aborts frequently.</p>
</li>
</ul>
</li>
<li><p><strong>Exit Code 139</strong> – This is the infamous <strong>segmentation fault (SIGSEGV)</strong>[10]. The process tried to access memory it shouldn’t (invalid pointer, buffer overflow, etc.), and the OS killed it. This is almost always a bug in the application code (or a library it’s using).</p>
<ul>
<li><p><strong>Why it happens:</strong> A segfault can be caused by many things: using a null pointer, reading/writing out of bounds, incompatible native libraries, etc. In some cases, even running out of stack can cause a segfault.</p>
</li>
<li><p><strong>What to do:</strong> As with 134, the primary action is to check application logs or enable core dumps for debugging. If the segfault happens on startup, it could be an incompatibility (for example, wrong CPU architecture or missing dependencies causing a segfault). Ensure the image is built for the correct architecture. Preq’s rule for 139 will basically alert you that a container hit SIGSEGV. It can’t fix the code, but it ensures you notice the crash.</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-detecting-exit-codes-with-a-unified-command"><strong>Detecting exit codes with a unified command</strong></h3>
<p>You can quickly scan your cluster for any pods that terminated with these exit codes using this exact raw text feeder to scan for exit codes and pipe into Preq:</p>
<table><tbody><tr><td><p>kubectl get pods --all-namespaces -o json | jq -r '<br />.items[] as $p<br />| [ ($p.status.containerStatuses // []),<br />($p.status.initContainerStatuses // []),<br />($p.status.ephemeralContainerStatuses // []) ]<br />| add<br />| .[]<br />| (.lastState.terminated // .state.terminated) as $t<br />| select($t != null and $t.exitCode != null and $t.finishedAt != null)<br />| [ $t.finishedAt,<br />($p.metadata.namespace + "/" + $p.metadata.name),<br />.name,<br />($t.reason // ""),<br />($t.exitCode|tostring) ]<br />| @TSV' | preq</p></td></tr></tbody></table>

<h2 id="heading-conclusion-using-preq-in-your-daily-workflow"><strong>Conclusion: Using Preq in Your Daily Workflow</strong></h2>
<p>In an ideal world, you can catch problems before they cause downtime  and that’s where Preq shines. Adopting preq in your day-to-day Kubernetes workflows can significantly reduce mean-time-to-detection for issues:</p>
<ul>
<li><p><strong>CI/CD Integration:</strong> Consider running Preq as a post-deploy check in your continuous deployment pipeline. For example, after deploying a new version of an application, have a step that runs kubectl preq on that namespace or on the specific new pods.</p>
</li>
<li><p><strong>Proactive scheduled runs:</strong> Use <strong>kubectl preq -j</strong> to generate a Kubernetes CronJob template. It writes <strong>cronjob.yaml</strong>. Open the file, set the schedule, add the Preq command you want to run including any <strong>-a</strong> action and <strong>-o</strong> output, set the namespace, then apply it with <strong>kubectl apply -f cronjob.yaml</strong></p>
</li>
</ul>
<p><strong>Note</strong> that <strong>kubectl preq</strong> does not support an all namespaces flag. To scan many targets, pass a data source template to Preq or wrap multiple invocations in a small script that the CronJob runs.</p>
<ul>
<li><strong>Post-mortem and Continuous Improvement:</strong> After any incident or outage, consider writing a new CRE rule (and contributing it!) if it was a novel issue. Preq’s framework lets you codify that knowledge so that neither you nor anyone else gets bitten by the same problem twice.</li>
</ul>
<p>In summary, Preq is a powerful ally for Kubernetes users. It turns the wealth of community experience with failure modes into actionable insights you can run on-demand. By incorporating Preq into CI/CD pipelines, scheduled scans, and troubleshooting sessions, you can <strong>proactively detect and resolve issues</strong> – often before they turn into user-facing incidents. Happy monitoring, and may your clusters run clean and healthy!</p>
<p>If you’re looking for enterprise features such as:</p>
<ul>
<li><p>a distributed detection engine that runs across many nodes and clusters</p>
</li>
<li><p>a web UI with guided workflows for investigation and collaboration</p>
</li>
<li><p>deeper integrations (for incident tracking, etc.)</p>
</li>
<li><p>a control plane for managing the distributed engine</p>
</li>
<li><p>a larger, proprietary set of CRE rules maintained by the Prequel Reliability Research team (PRRT).</p>
</li>
</ul>
<p>Check out <a target="_blank" href="https://www.prequel.dev/sign-up">Prequel</a>, our commercial offering and let us know what you think!</p>
<hr />
<p>[1] <a target="_blank" href="https://www.prequel.dev/blog-post/dev-to-10-kubectl-plugins-that-help-make-you-the-most-valuable-kubernetes-engineer-in-the-room">Dev.to: 10 kubectl Plugins That Help Make You the Most Valuable Kubernetes Engineer in the Room</a></p>
<p>[2] <a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0119">CRE-2025-0119 | Prequel</a></p>
<p>[3] <a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0071">CRE-2025-0071 | Prequel</a></p>
<p>[4] <a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0048">CRE-2025-0048 | Prequel</a></p>
<p>[5] <a target="_blank" href="https://docs.prequel.dev/cres/public/cre-2025-0125">CRE-2025-0125 | Prequel</a></p>
<p>[6] <a target="_blank" href="https://stackoverflow.com/questions/59729917/kubernetes-pods-terminated-exit-code-137?utm_source=chatgpt.com">Stack Overflow: Kubernetes Pods Terminated Exit Code 137</a></p>
<p>[7] <a target="_blank" href="https://github.com/prequel-dev/cre/pull/137">Exit Code CREs | Prequel</a></p>
<p>[8] <a target="_blank" href="https://krew.sigs.k8s.io/docs/user-guide/setup/install/">Installing Krew</a></p>
<p>[9] <a target="_blank" href="https://docs.prequel.dev/running#scheduled-jobs">Schedule preq to run in a Cronjob</a></p>
]]></content:encoded></item><item><title><![CDATA[Bitnami’s Free Catalog Says Goodbye: Avoid Brownouts and a $72k Surprise]]></title><description><![CDATA[TLDR,

Bitnami is narrowing public access to images and pausing updates to many chart artifacts. Expect brownouts as the cut-over window starts on Aug 28th with final public catalog deletion on Sept 29th 

The biggest risks: 

Kubernetes ImagePullBac...]]></description><link>https://prequel.hashnode.dev/bitnamis-free-catalog-says-goodbye-avoid-brownouts-and-a-72k-surprise</link><guid isPermaLink="true">https://prequel.hashnode.dev/bitnamis-free-catalog-says-goodbye-avoid-brownouts-and-a-72k-surprise</guid><category><![CDATA[bitnami]]></category><category><![CDATA[Devops]]></category><category><![CDATA[Docker]]></category><category><![CDATA[Kubernetes]]></category><category><![CDATA[Reliability]]></category><dc:creator><![CDATA[Lyndon Brown]]></dc:creator><pubDate>Thu, 11 Sep 2025 18:53:15 GMT</pubDate><enclosure url="https://cdn.hashnode.com/res/hashnode/image/upload/v1757616290279/6914d5c2-7f45-4d04-970b-f6b6b5f77ecc.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><strong>TLDR,</strong></p>
<ul>
<li><p>Bitnami is narrowing public access to images and pausing updates to many chart artifacts. Expect brownouts as the cut-over window starts on Aug 28th with final public catalog deletion on Sept 29th </p>
</li>
<li><p>The biggest risks: </p>
<ul>
<li><p>Kubernetes ImagePullBackOff on restarts or during  autoscaling,</p>
</li>
<li><p>stale/unpatched images (CVE drift),</p>
</li>
<li><p>chart drift and subchart dependencies that break upgrades.</p>
</li>
</ul>
</li>
<li><p>We’re publishing <strong>CREs</strong> (Common Reliability Enumerations) that help you quickly identify Bitnami-related risks and resolve them.   </p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757616752834/08c4c1b0-e7c8-43f3-8385-23b78b07f66b.png" alt /></p>
<p><em>stonesabe4 on</em> <a target="_blank" href="https://www.reddit.com/r/kubernetes/comments/1n2gc8d/basically_just_found_out_i_need_to_72k_for/"><em>reddit</em></a></p>
<h1 id="heading-why-bitnami-mattered"><strong>Why Bitnami mattered</strong></h1>
<p>For years, Bitnami’s images and Helm charts were the de-facto path to running popular apps on Kubernetes. Well-maintained images, sensible defaults, and easy Helm installs. Many teams pinned Bitnami images in deployments, CI pipelines, and internal charts.</p>
<h1 id="heading-whats-changing"><strong>What’s changing</strong></h1>
<p>Bitnami is making a number of changes following their acquisition by Broadcom and renewed focus on a subscription model. </p>
<ul>
<li><p><strong>Catalog changes.</strong> The container repos are undergoing a major shift.  </p>
<ol>
<li><p>The existing docker.io/bitnami public repo will be deleted.   </p>
</li>
<li><p>A new repo docker.io/bitnamisecure will contain hardened community images, but there is a catch. It will only contain the latest tags and these images are intended for development only.     </p>
</li>
<li><p>Existing container images will be moved to a new repo docker.io/bitnamilegacy, but will receive no further updates.</p>
</li>
</ol>
</li>
<li><p><strong>Charts stop updating.</strong> Bitnami’s Pre-built Helm chart artifacts won’t be updated anymore, so their defaults keep pointing to old images; you’ll need to override image repos/tags or adopt alternatives.</p>
</li>
</ul>
<p><strong>Brownouts &amp; cutoff windows.</strong> Bitnami has planned 24-hour outages for selected images.  For each scheduled brownout, ten container images from docker.io/bitnami will be taken offline for a 24-hour period. The specific applications impacted will be shared on the day the brownout begins. Final cutoff will occur on Sept 29. </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757616657681/63684c27-3703-4a28-8ab6-1f5b2d54fc3e.png" alt class="image--center mx-auto" /></p>
<h1 id="heading-whos-affected"><strong>Who’s affected</strong></h1>
<p>If you use any of these, read on:</p>
<ul>
<li><p><strong>Pinned or Unpinned Bitnami image tags</strong> (e.g., <a target="_blank" href="http://docker.io/bitnami/postgresql:13.x">docker.io</a>/<a target="_blank" href="http://docker.io/bitnami/postgresql:13.x">bitnami/postgresql:13.x</a>, :latest) in Deployments/StatefulSets/Jobs.</p>
</li>
<li><p><strong>Bitnami-based charts</strong> in helmfile/Argo CD/Flux pipelines.</p>
</li>
<li><p><strong>CI pipelines</strong> <strong>that pull Bitnami tools</strong> (kubectl, kubectl-helm, db images, etc.)</p>
</li>
</ul>
<p><strong>What will the impact be?</strong></p>
<ul>
<li><p><strong>Kubernetes ErrImagePull / ImagePullBackOff</strong> on pod restarts, scale-outs, node drains, or fresh deploys.</p>
</li>
<li><p><strong>Time-bomb restarts.</strong> Running pods look fine until the <em>next</em> pull (then fail).</p>
</li>
<li><p><strong>Security drift.</strong> Stale/archived images stop receiving fixes and lead to accumulated CVEs.</p>
</li>
<li><p><strong>Chart drift.</strong> Defaults reference repos/tags that no longer update leading to failed upgrades or silent divergence.</p>
</li>
</ul>
<h1 id="heading-doing-a-manual-impact-assessment"><strong>Doing a manual impact assessment</strong></h1>
<p>Here are a few steps you can take to understand your exposure and mitigate associated risk. </p>
<ol>
<li><strong>Inventory images:  
 </strong>kubectl get pods -A -o json | jq -r '..|.image? // empty' | sort -u | grep -i bitnami</li>
</ol>
<p><strong>Search configs &amp; charts:</strong> grep your helmfiles/values/overlays for bitnami and pinned tags.</p>
<h1 id="heading-automated-approach-new-cres-to-help-you-navigate-the-bitnami-change"><strong>Automated Approach: New CREs to help you navigate the Bitnami change</strong></h1>
<p>We’re publishing a focused set of <strong>Common Reliability Enumerations (CREs)</strong> to help you surface issues:</p>
<ul>
<li><p><strong>PREQUEL-2025-0102-Deprecated Pulling Deprecated Bitnami Images  
  </strong>Detects workloads pulling Bitnami images scheduled to be deleted or moved.   </p>
</li>
<li><p><strong>PREQUEL-2025-0103 PullingUnmaintained Bitnami Images  
  </strong>Detects workloads pulling from unmaintained legacy repo. </p>
</li>
<li><p><strong>PREQUEL-2025-0104 Pulling Latest-Only-Non-Prod Images  
  </strong>Detects workloads pulling images from the latest-only non-prod repo. </p>
</li>
</ul>
<p><strong>PREQUEL-2025-0105 Deployment Tied to Deprecated Bitnami Images  
</strong>Finds deployments who l reference deprecated image locations.<br />These CREs are cluster- and pipeline-friendly: run them pre-deployment (CI), in staging, and periodically in prod to address issues and ensure regressions don’t slip back in.</p>
<h1 id="heading-using-prequel-to-catch-bitnami-risks-before-they-break-prod"><strong>Using Prequel to catch Bitnami risks before they break prod</strong></h1>
<p><strong>Prequel</strong> is the enterprise reliability problem detection platform (from the team behind the open source Preq and CRE projects). It runs CREs continuously, examining and correlating cluster events/logs/configs, and providing guided fixes.</p>
<h3 id="heading-why-prequel-vs-doing-this-by-hand"><strong>Why Prequel (vs. doing this by hand)</strong></h3>
<ul>
<li><p><strong>Larger exclusive CRE library covering 100s of popular technologies</strong> maintained by the <strong>Prequel Reliability Research Team (PRRT</strong>).</p>
</li>
<li><p><strong>Distributed detection engine</strong> that connects the dots across nodes and clusters.</p>
</li>
<li><p><strong>Web UI</strong> with guided workflows for investigation &amp; collaboration.</p>
</li>
<li><p><strong>Deep integrations</strong> (incident tracking, chat, CI/CD).</p>
</li>
<li><p><strong>Control plane</strong> to manage rules, sensors, and rollouts.</p>
</li>
</ul>
<p><strong>You can use Prequel to continuously scan for these and other risks.</strong> (Sign up for a 30-day free trial. No credit card required)  </p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1757616678263/7d72905a-cb3c-48af-b1ee-0b2f2da46fc4.png" alt class="image--center mx-auto" /></p>
<p>Sneak Peek of <a target="_blank" href="https://docs.prequel.dev/cres/commercial">Prequel Rules</a> Catalog </p>
<h1 id="heading-pragmatic-bitnami-risk-migration-options"><strong>Pragmatic Bitnami risk migration options</strong></h1>
<p>Once you understand your exposure using an automated or manual method, there are a number of steps you can take.   </p>
<ul>
<li><p><strong>Identify new registries.</strong>  Evaluate alternatives such as Docker Official or Hardened Images, Chainguard, to see what meets your needs and budget. </p>
</li>
<li><p><strong>Mirror first, then refactor.</strong> Point bitnami images to a private registry mirror for faster pulls and no cut off, then replace images/charts on your schedule.</p>
</li>
<li><p><strong>Pin by digest.</strong> Use immutable digests to lock the exact image you want, unlike tags which may move/disappear.</p>
</li>
<li><p><strong>Automate gates.</strong> Fail builds when CREs detect deprecated Bitnami pulls in manifests or pipelines.</p>
</li>
<li><p><strong>Prove in staging.</strong> Force a rolling restart <em>before</em> a cutoff window; verify image pulls and readiness gates.</p>
</li>
<li><p><strong>Document the new defaults.</strong> Put the new repo/tag/digest and patch cadence where your team can’t miss it.</p>
</li>
</ul>
<h1 id="heading-wrap-up"><strong>Wrap-up</strong></h1>
<p>Ecosystem shifts like this can break prod today, or break on your next upgrade.  It is increasingly impossible to keep up with all the risks that affect your stack.  If you need help, let <strong>Prequel</strong> keep watch for these and 100s of other daily risks.  <strong>Try Prequel</strong> and stay ahead of breaking ecosystem changes: <a target="_blank" href="https://www.prequel.dev/sign-up">https://www.prequel.dev/sign-up</a></p>
]]></content:encoded></item></channel></rss>