<?xml version="1.0" encoding="UTF-8"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Ankra Blog</title><description>Practical guides on platform engineering, GitOps, AI-driven incident response, and shipping to Kubernetes without the toil.</description><link>https://ankra.ai</link><language>en</language><item><title>Ankra is now ankra.ai: Rewritten in Go, Ready for What&apos;s Next</title><link>https://ankra.ai/blog/ankra-is-now-ankra-ai</link><guid isPermaLink="true">https://ankra.ai/blog/ankra-is-now-ankra-ai</guid><description>A new name, a new engine, and the biggest release we have ever shipped: the Go rewrite, an AI that owns the incident loop, passkey security, European multi-cloud, and Ankra on your phone.</description><pubDate>Mon, 06 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The product has been pointing at this for a year: an AI that runs your operations, not one that just answers questions about them. This month the name caught up. Ankra is now &lt;strong&gt;ankra.ai&lt;/strong&gt;. Same platform, same clusters, new center of gravity.&lt;/p&gt;
&lt;p&gt;Underneath the new name sits the biggest engineering release we have ever shipped. Here is everything that landed since March: the Go rewrite, an AI that owns the incident loop, a complete identity stack, European managed multi-cloud, and Ankra on your phone.&lt;/p&gt;
&lt;h2 id=&quot;ankra-goes-all-the-way-with-go&quot;&gt;Ankra goes all the way with Go&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#ankra-goes-all-the-way-with-go&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/section-go-performance.png&quot; alt=&quot;Built with Go: a performance curve bending up&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Over the past two quarters we re-engineered the Ankra Agent and the Ankra backend in Go: the API, the work schedulers, the maintenance loops, the GitOps reconciler, and the chat pipeline. Performance is now a first-class focus, and the gains are platform-wide. Go has taken our headroom to &lt;strong&gt;25x the scale on the same footprint&lt;/strong&gt;, and the speed-up is felt everywhere, from API responses to reconciles to chat. As Ankra picks up traction, this is the foundation we are building toward enterprise-grade scale.&lt;/p&gt;
&lt;p&gt;What that means in practice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A fraction of the footprint.&lt;/strong&gt; The agent now runs with a 512Mi memory limit, down from 1536Mi. Same reconcile work, a third of the reservation, on every cluster you run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Built to scale 25x.&lt;/strong&gt; No runtime to warm up, no interpreter in the path. Go lets the platform absorb an order of magnitude more load, so performance holds as you grow into enterprise-grade fleets.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Zero action required.&lt;/strong&gt; The Go agent on the &lt;code&gt;2.0.x&lt;/code&gt; track is a drop-in replacement, rolled out across the fleet automatically. Your stacks, operations, and workflows carry over untouched.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One binary everywhere.&lt;/strong&gt; A single statically compiled binary per platform. No dependency tree, no runtime patching, a smaller surface to attack and to audit.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;describe-the-problem-approve-the-fix&quot;&gt;Describe the problem. Approve the fix.&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#describe-the-problem-approve-the-fix&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/section-ai-operations.png&quot; alt=&quot;The AI assistant drafts a plan and waits for your approval&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Most of every incident is spent collecting evidence. The AI assistant now owns that loop: tell it the symptom and it correlates logs, events, manifests, metrics, Stack history, and Git state, drafts a multi-step plan, and executes it with your approval at every mutating step. It remembers context across conversations, reaches your own tools over MCP, and nothing changes without you. Between incidents, AI Insights keeps scanning, adapting to what your clusters actually run.&lt;/p&gt;
&lt;p&gt;Prefer your own agent? Point Cursor, Claude Code, or anything with a terminal at the Ankra CLI and it becomes a cluster-aware infrastructure subagent: real cluster state, incident triage with &lt;code&gt;ankra chat&lt;/code&gt;, and every change landing as a reviewable draft, never a raw &lt;code&gt;kubectl edit&lt;/code&gt;. We wrote a full guide on &lt;a href=&quot;/blog/cursor-ankra-ai-subagent&quot;&gt;wiring Cursor up as an Ankra subagent&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;security-that-keeps-up-with-you&quot;&gt;Security that keeps up with you&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#security-that-keeps-up-with-you&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This quarter shipped a complete identity stack. Native two-factor authentication and multi-social sign-in, built into every surface you use: browser, CLI, and now mobile.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Passkeys, natively.&lt;/strong&gt; Sign in with Touch ID, Face ID, or Windows Hello, the credential your device already trusts, with hardware security keys and authenticator-app codes (TOTP) alongside, and one unified set of recovery codes.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Step-up at every sign-in.&lt;/strong&gt; Verification happens on each login, and &lt;code&gt;ankra login&lt;/code&gt; completes MFA in the browser before dropping you back in the terminal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Enforce it for the whole organisation.&lt;/strong&gt; Require MFA org-wide, with admin reset for locked-out teammates.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Sign in your way.&lt;/strong&gt; Google, Apple, GitHub, or email and password. Link them to one account from Profile → Authentication.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Beyond login.&lt;/strong&gt; Trivy Operator vulnerability reports on a dedicated cluster Security page, kubeconfigs that expire on their own, &lt;code&gt;--strict-secrets&lt;/code&gt; validation in CI, and checksum-verified CLI upgrades.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-platform-in-your-pocket&quot;&gt;The platform, in your pocket&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-platform-in-your-pocket&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/section-mobile.png&quot; alt=&quot;Ankra Mission Control on iOS and Android&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Ankra is now on iOS and Android in beta. Mission Control, cluster health, live operations, AI chat, and AI Insights, from wherever the page finds you. And the security stack above is built in from the first unlock: Face ID or Touch ID on iOS, BiometricPrompt on Android, automatic re-lock the moment the app leaves the foreground, device passcode as the fallback.&lt;/p&gt;
&lt;p&gt;The beta ships through TestFlight and Google Play internal testing. &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;Reach out on Slack&lt;/a&gt; and we will send you an invite.&lt;/p&gt;
&lt;h2 id=&quot;european-by-default-sovereign-by-design&quot;&gt;European by default. Sovereign by design.&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#european-by-default-sovereign-by-design&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/section-multicloud-europe.png&quot; alt=&quot;Managed multi-cloud Kubernetes across Europe&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Ankra was founded in Sweden and built for Europe, and our managed clusters reflect it. Provision and run production Kubernetes on Hetzner, OVH, and UpCloud, three European clouds, from one console and one set of commands. Your control plane, your data, and your workloads stay on the continent, under EU jurisdiction. No hyperscaler lock-in, no data leaving the region unless you choose it.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Three European clouds, one workflow.&lt;/strong&gt; Create, scale, upgrade, and deprovision with the same provider-agnostic commands, wherever the cluster runs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Data residency you control.&lt;/strong&gt; Keep clusters and data inside the EU, close to your users and inside your regulatory perimeter, without giving up the managed experience of a hyperscaler.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Roots in Sweden and the EU.&lt;/strong&gt; We are a European company by conviction, not convenience. Digital sovereignty is not a feature we bolted on; it is the reason Ankra exists.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No lock-in, ever.&lt;/strong&gt; Standard Kubernetes, GitOps as the source of truth, and clusters you can move between providers. Your platform is yours to take anywhere.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;deploying-your-app&quot;&gt;Deploying your app&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#deploying-your-app&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/ui-applications.png&quot; alt=&quot;Applications in Ankra: repositories running as stacks&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Connect a repo, get a running app.&lt;/strong&gt; Applications takes a repository and generates the Dockerfile, Helm chart, and CI pipeline as a pull request, then deploys the result to your cluster as a stack. Review the PR. That is the whole handoff. It is in closed beta today: open Applications in the platform to &lt;a href=&quot;https://platform.ankra.app/organisation/applications&quot;&gt;join the waitlist&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/ui-app-pipeline.png&quot; alt=&quot;An Ankra Application: commit to build to security scan to manifests to deploy to live&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Commit to live in one view: the delivery pipeline, image vulnerabilities, and the GHCR artifact, all tracked per application.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Capture a working stack once, apply it anywhere.&lt;/strong&gt; Stack Profiles turn a proven stack into a versioned template for any cluster: &lt;code&gt;ankra stack-profiles get&lt;/code&gt; and &lt;code&gt;apply&lt;/code&gt; from the CLI, with &lt;code&gt;--category&lt;/code&gt; to browse by what they do.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Take the safe path to production.&lt;/strong&gt; &lt;code&gt;ankra cluster draft&lt;/code&gt; stages the change, &lt;code&gt;validate --strict-secrets&lt;/code&gt; fails CI before a plaintext secret lands in Git, then deploy with &lt;code&gt;--watch&lt;/code&gt; and follow it land from the terminal. Changing one value? Helm-style &lt;code&gt;--set&lt;/code&gt; patches it atomically, with &lt;code&gt;--dry-run&lt;/code&gt; to preview first.&lt;/p&gt;
&lt;h2 id=&quot;maintaining-your-app&quot;&gt;Maintaining your app&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#maintaining-your-app&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/newsletter/july26/ui-dashboard.png&quot; alt=&quot;The Ankra dashboard: fleet map, live operations, and cost at a glance&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Retire the ArgoCD runbook.&lt;/strong&gt; Ankra’s own engine now &lt;a href=&quot;/blog/native-deployment-engine&quot;&gt;reconciles your clusters natively&lt;/a&gt;: nothing to install, upgrade, or unstick, and the same Git-as-source-of-truth workflow. Existing clusters migrate addon-by-addon.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One set of verbs for every cloud.&lt;/strong&gt; &lt;code&gt;ankra cluster upgrade&lt;/code&gt;, &lt;code&gt;scale&lt;/code&gt;, &lt;code&gt;node-group&lt;/code&gt;: the same commands wherever the cluster lives. The provider is a detail, not a prefix you have to remember.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Upgrades that don’t gamble with your workloads.&lt;/strong&gt; &lt;code&gt;ankra cluster upgrade&lt;/code&gt; now covers kubeadm clusters alongside k3s: one node at a time, control plane first, each node cordoned and drained respecting PodDisruptionBudgets, with an etcd snapshot taken before the control plane moves. A blocked drain aborts safely; &lt;code&gt;--force&lt;/code&gt; only when you say so.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Stop paying for idle clusters.&lt;/strong&gt; Delete a cloud cluster’s infrastructure to stop the charges while it stays registered in Ankra, then restore it on demand, even reshaped: controllers, instance types, node groups.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Clone environments, not runbooks.&lt;/strong&gt; Select every stack and clone to another cluster, even across organisations, in one operation, name conflicts resolved automatically and variables resolving per scope so the clone fits its new home.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;See the whole fleet at a glance.&lt;/strong&gt; Operations live-update as they run, PromQL queries work straight from the CLI, and the dashboard puts your fleet on a world map with cloud cost beside it.&lt;/p&gt;
&lt;h2 id=&quot;also-shipped&quot;&gt;Also shipped&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#also-shipped&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;On Bitbucket? You’re in.&lt;/strong&gt; Bitbucket Cloud joins GitHub as a GitOps provider, and GitHub users can switch to App installs, with scoped, revocable access instead of long-lived personal tokens.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;kubeadm, end to end.&lt;/strong&gt; &lt;code&gt;ankra cluster kubeadm-versions&lt;/code&gt; lists upgrade targets, and cloud creates take &lt;code&gt;--etcd-topology&lt;/code&gt; stacked or external with 3- or 5-node dedicated etcd.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Two-factor from the terminal.&lt;/strong&gt; &lt;code&gt;ankra profile auth&lt;/code&gt; enrolls, lists, and removes MFA methods without opening a browser tab.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The CLI updates itself.&lt;/strong&gt; &lt;code&gt;ankra upgrade&lt;/code&gt; takes you to v0.5.0 with a verified checksum and swaps the binary in place; pin a version to roll back.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;One terminal, many targets.&lt;/strong&gt; Global &lt;code&gt;--org&lt;/code&gt; and &lt;code&gt;--cluster&lt;/code&gt; flags apply per request, and kubeconfigs now pin the owning organisation, so kubectl keeps working after you switch orgs.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stack edits without opening the UI.&lt;/strong&gt; Edit dependency ordering, print addon values or manifest YAML, delete manifests, and keep node SSH keys in sync (&lt;code&gt;ankra ssh-keys get/set/resync&lt;/code&gt;) from the CLI.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Guardrails for scripts and humans alike.&lt;/strong&gt; A documented exit-code contract so pipelines branch on the failure class, and every destructive command confirms before acting.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Claude Code joins Cursor.&lt;/strong&gt; &lt;code&gt;ankra skills --editor claude-code&lt;/code&gt; installs the curated Ankra practices into your coding agent of choice.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The CLI reference writes itself.&lt;/strong&gt; Generated from the command tree and synced to the docs on every release, so the reference never drifts from the binary you run.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Removed: add-on subscriptions.&lt;/strong&gt; Add-ons are now managed directly on the cluster or stack; legacy subscription endpoints return &lt;code&gt;410 Gone&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-the-name-changed&quot;&gt;Why the name changed&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#why-the-name-changed&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A year ago, Ankra was where you managed Kubernetes. Today it is where you deploy an app, keep it healthy, and hand the 3am incident to an agent that fixes it with your approval, from a terminal, a browser, or the phone on your nightstand. ankra.ai is not a rebrand. It is a description.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Faster than you remember it. Same clusters, new engine. &lt;a href=&quot;https://platform.ankra.app&quot;&gt;Open Ankra&lt;/a&gt; or read the &lt;a href=&quot;/changelog&quot;&gt;full changelog&lt;/a&gt;.&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Engineering</category><category>AI</category><category>Security</category><category>Platform Engineering</category><category>Kubernetes</category></item><item><title>Secrets Belong in Git. Plaintext Does Not.</title><link>https://ankra.ai/blog/gitops-secrets-sops-age</link><guid isPermaLink="true">https://ankra.ai/blog/gitops-secrets-sops-age</guid><description>Every GitOps rollout stalls on one question: where do the secrets go? A practical guide to SOPS and AGE encryption in Ankra, so credentials live in Git safely and AI-generated config never leaks a key.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every GitOps rollout hits the same wall, usually in week two. The team agrees Git should be the source of truth. The cluster definition goes into a repo. The Helm values follow. Then someone tries to commit the Postgres password and the whole plan stalls in a meeting about “how we handle secrets,” and three sprints later half the configuration lives in Git and the other half lives in a vault nobody wired up, a CI variable nobody documented, and a &lt;code&gt;.env&lt;/code&gt; file that gets passed around in Slack DMs.&lt;/p&gt;
&lt;p&gt;We have written a lot on this blog about Git as the source of truth: &lt;a href=&quot;/blog/building-pipeline-agents-with-ankra-cli&quot;&gt;pipeline agents that review cluster changes on pull requests&lt;/a&gt;, &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;AI that proposes drafts instead of touching production&lt;/a&gt;, &lt;a href=&quot;/blog/clone-production-environments-with-stacks&quot;&gt;stacks that clone from a laptop to production&lt;/a&gt;. All of it assumes an answer to the question this post finally tackles head-on: if Git holds everything, where do the credentials go?&lt;/p&gt;
&lt;p&gt;The answer is that they go in Git too, encrypted, with a workflow that makes the safe path the default path. Here is how that works, why the alternatives fail, and how Ankra makes it a one-time setup instead of a platform project.&lt;/p&gt;
&lt;h2 id=&quot;the-numbers-got-worse-and-ai-is-making-them-worse-faster&quot;&gt;The numbers got worse, and AI is making them worse faster&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-numbers-got-worse-and-ai-is-making-them-worse-faster&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;GitGuardian’s State of Secrets Sprawl report has been the industry’s yearly cold shower for half a decade. The 2026 edition is the coldest yet: 28.65 million new hardcoded secrets landed in public GitHub commits during 2025, a 34 percent jump year over year and the largest single-year increase they have ever recorded.&lt;/p&gt;
&lt;p&gt;Two findings in that report matter specifically for infrastructure teams.&lt;/p&gt;
&lt;p&gt;First, AI-assisted commits leak secrets at roughly double the baseline rate. Coding assistants reproduce the patterns they were trained on, and the training data is full of API keys pasted into examples and passwords hardcoded in test fixtures. As more of your YAML gets written by an agent, the odds of a credential slipping into a commit go up, not down.&lt;/p&gt;
&lt;p&gt;Second, the report found six times more hardcoded secrets in internal repositories than in public ones. Teams behave as if a private repo is a security boundary. It is not, and there is a well-known incident that proves it.&lt;/p&gt;
&lt;h2 id=&quot;the-repo-is-private-is-not-a-secrets-strategy&quot;&gt;”The repo is private” is not a secrets strategy&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-repo-is-private-is-not-a-secrets-strategy&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In April 2024, attackers got into the self-managed GitLab instance of Sisense, a business intelligence company whose product connects to its customers’ data sources. Inside that private repository they found hardcoded AWS credentials. Those credentials opened the company’s S3 buckets, and terabytes of customer data walked out: access tokens, passwords, SSL certificates. The breach was serious enough that CISA issued an alert telling every Sisense customer to rotate every credential they had ever shared with the platform.&lt;/p&gt;
&lt;p&gt;Note what failed there. Not the firewall, not the cluster, not the cloud account. A private Git repository was treated as a safe place for plaintext credentials, and a single compromised repo converted into full cloud access.&lt;/p&gt;
&lt;p&gt;The lesson is not “keep secrets out of Git.” Config that references secrets without containing them just moves the problem somewhere with less review, less history, and less audit trail. The lesson is that a secret in Git must be worthless to anyone who reads it.&lt;/p&gt;
&lt;p&gt;And one more number, because it explains why leaks hurt for years instead of days: GitGuardian found that 64 percent of the secrets they detected in 2022 were still valid in January 2026. Most teams do not rotate. The secret that leaks today is the secret that gets used against you in three years.&lt;/p&gt;
&lt;h2 id=&quot;encrypt-values-not-files&quot;&gt;Encrypt values, not files&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#encrypt-values-not-files&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The tool for this job is &lt;a href=&quot;https://github.com/getsops/sops&quot;&gt;SOPS&lt;/a&gt;, and the detail that makes it the right tool is that it encrypts the values in a YAML file while leaving the keys and structure readable.&lt;/p&gt;
&lt;p&gt;That distinction sounds small. It is everything. A fully encrypted blob cannot be reviewed: a pull request that changes it is a diff between two walls of base64, and your review process degrades to “approve and hope.” A SOPS-encrypted file keeps its shape:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Secret&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;postgres-credentials&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;database&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Opaque&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;stringData&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app_user&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ENC[AES256_GCM,data:vxvYs7vKw+bPqNWO3tE=,iv:...,tag:...,type:str]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;sops&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;age&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;recipient&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;encrypted_regex&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;^(password)$&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3.9.4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: v1kind: Secretmetadata:  name: postgres-credentials  namespace: databasetype: OpaquestringData:  username: app_user  password: ENC[AES256_GCM,data:vxvYs7vKw+bPqNWO3tE=,iv:...,tag:...,type:str]sops:  age:    - recipient: age1ql3z7hjy54pw3hyww5ayyfg7zqgvc7w3j2elw8zmrj2kg5sfn9aqmcac8p  encrypted_regex: ^(password)$  version: 3.9.4&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;A reviewer can see that this is a Secret, in the &lt;code&gt;database&lt;/code&gt; namespace, that the username changed, and that the password is ciphertext. The commit is safe to push to any repo, public or private, because the value is encrypted with AES256 and only the holder of the private key can recover it.&lt;/p&gt;
&lt;p&gt;For the key pair itself, Ankra uses &lt;a href=&quot;https://github.com/FiloSottile/age&quot;&gt;AGE&lt;/a&gt; rather than PGP. AGE is a modern, deliberately boring encryption tool: one public key that encrypts, one private key that decrypts, no keyservers, no trust ceremonies, no twenty-year-old tooling to fight. The public key is shareable by design. The private key is the only thing that matters, and in Ankra’s setup, no human ever handles it.&lt;/p&gt;
&lt;h2 id=&quot;the-ankra-workflow-initialize-once-encrypt-by-default&quot;&gt;The Ankra workflow: initialize once, encrypt by default&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-ankra-workflow-initialize-once-encrypt-by-default&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most SOPS guides now ask you to generate keys, distribute them to every cluster, patch your CD tooling with a decryption plugin, and write a &lt;code&gt;.sops.yaml&lt;/code&gt; policy file. That setup cost is exactly why teams postpone secrets hygiene until after the incident.&lt;/p&gt;
&lt;p&gt;In Ankra it is one step. Go to Organisation Settings, open Encryption, and click Initialize Encryption. The platform generates an AGE key pair, shows you the public key, and stores the private key in its vault. From that moment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Encryption is on by default.&lt;/strong&gt; Any field you mark as encrypted is protected the moment you save.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Decryption is automatic.&lt;/strong&gt; The Ankra agent on each cluster decrypts values at deploy time by running &lt;code&gt;sops --decrypt&lt;/code&gt; directly, as part of Ankra’s native deployment engine. The AGE private key is fetched from the platform for the render and is not stored on the cluster, so there is no key Secret sitting in a namespace waiting to be read. There is nothing to configure per cluster, whether you run three clusters or fifty.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The flow, end to end: you type a plaintext value in the Stack Builder, Ankra encrypts it with your organisation’s public key on save, the &lt;code&gt;ENC[AES256_GCM,...]&lt;/code&gt; ciphertext is what gets committed to your GitOps repository, and the agent decrypts it at deploy time. Plaintext exists in the editor and in the running workload. It never exists in Git, and the decryption key never lives on the cluster.&lt;/p&gt;
&lt;h3 id=&quot;in-the-stack-builder&quot;&gt;In the Stack Builder&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#in-the-stack-builder&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When you edit a manifest or an addon’s Helm values, there is an Encrypted Keys (SOPS) section. Add the key names that are sensitive, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;apiKey&lt;/code&gt;, &lt;code&gt;token&lt;/code&gt;, &lt;code&gt;adminPassword&lt;/code&gt;, and enter values normally. Only the listed keys get encrypted; everything else stays readable, so reviews and debugging keep working.&lt;/p&gt;
&lt;h3 id=&quot;from-the-cli-for-gitops-first-teams&quot;&gt;From the CLI, for GitOps-first teams&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#from-the-cli-for-gitops-first-teams&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;If your cluster definition lives in a repo and you edit it locally, the &lt;a href=&quot;https://docs.ankra.ai/integrations/ankra-cli&quot;&gt;Ankra CLI&lt;/a&gt; does the same thing in file mode. Encrypt a key in a Secret manifest before committing:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Inspect the public key your org encrypts with&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;sops-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Encrypt the password in a manifest referenced by cluster.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;encrypt&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;manifest&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;db-secret&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--key&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-f&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Encrypt a sensitive Helm value on an addon&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;encrypt&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;addon&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--key&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;adminPassword&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-f&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster sops-configankra cluster encrypt manifest db-secret --key password -f cluster.yamlankra cluster encrypt addon --name grafana --key adminPassword -f cluster.yaml&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The CLI rewrites the referenced file with the encrypted value and records what it did in the cluster definition, so the platform knows which fields to decrypt at deploy time:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;manifests&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;db-secret&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from_file&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;manifests/db-secret.yaml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;encrypted_paths&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;password&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;addons&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;chart_name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;chart_version&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;9.2.10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;repository_url&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;https://grafana.github.io/helm-charts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;configuration&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from_file&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;values/grafana.yaml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;encrypted_paths&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;adminPassword&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;manifests:  - name: db-secret    from_file: &amp;quot;manifests/db-secret.yaml&amp;quot;    encrypted_paths:      - passwordaddons:  - name: grafana    chart_name: grafana    chart_version: 9.2.10    repository_url: https://grafana.github.io/helm-charts    namespace: monitoring    configuration:      from_file: &amp;quot;values/grafana.yaml&amp;quot;      encrypted_paths:        - adminPassword&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Need to check what a value actually is? Decryption prints to stdout and nowhere else:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;decrypt&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;manifest&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;db-secret&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-f&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster decrypt manifest db-secret -f cluster.yaml&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;make-plaintext-a-failed-build-not-a-code-review-comment&quot;&gt;Make plaintext a failed build, not a code review comment&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#make-plaintext-a-failed-build-not-a-code-review-comment&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Hygiene that depends on a reviewer noticing a credential at 5pm on a Friday is not hygiene. The check belongs in CI, where it is deterministic.&lt;/p&gt;
&lt;p&gt;Ankra’s validation command has a flag for exactly this. In the pull request pipeline that reviews your cluster changes, run:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;validate&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-f&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster.yaml&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--strict-secrets&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster validate -f cluster.yaml --strict-secrets&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Validation already checks your stack structure, chart references, and dependency wiring against the platform. With &lt;code&gt;--strict-secrets&lt;/code&gt;, a plaintext Secret or an unencrypted sensitive value stops being a warning and becomes a failed job. The pull request goes red before a human ever looks at it, and the credential never reaches the default branch.&lt;/p&gt;
&lt;p&gt;If you followed our &lt;a href=&quot;/blog/building-pipeline-agents-with-ankra-cli&quot;&gt;pipeline agents guide&lt;/a&gt;, you already have this workflow running; the flag is in it. This is the piece most secrets tutorials skip, and it is the piece that actually changes outcomes, because it removes the human from the failure path.&lt;/p&gt;
&lt;h2 id=&quot;the-ai-angle-agents-that-cannot-leak-what-they-never-hold&quot;&gt;The AI angle: agents that cannot leak what they never hold&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-ai-angle-agents-that-cannot-leak-what-they-never-hold&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is where the GitGuardian finding about AI-assisted commits stops being scary and starts being an architecture requirement. If AI writes a growing share of your configuration, and AI-assisted commits leak at twice the baseline rate, then the fix is not prompting the model to be careful. The fix is a pipeline where the unsafe output physically cannot land.&lt;/p&gt;
&lt;p&gt;Ankra’s AI operates under the same contract as everyone else: &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;it proposes drafts, humans approve, Git records the result&lt;/a&gt;. Sensitive values in those drafts are SOPS-encrypted before they leave the platform. The agent never holds your cloud credentials, and the commit it produces contains ciphertext, not keys. An AI that drafts a Grafana stack with an admin password produces an encrypted &lt;code&gt;adminPassword&lt;/code&gt;, because the encryption step is in the platform, not in the model’s judgment.&lt;/p&gt;
&lt;p&gt;Two related behaviors are worth knowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Secret variables are masking, not encryption.&lt;/strong&gt; Ankra variables can be marked secret, which hides them in the UI. That is a convenience feature. For anything that must be encrypted at rest in Git, use SOPS. The platform docs are explicit about this distinction, and now you are too.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Clones do not carry secrets.&lt;/strong&gt; When you clone a stack to another cluster or another organisation, encrypted values deliberately do not transfer. You reconfigure them in the target. Mildly annoying on purpose: the alternative is credentials silently propagating to environments they were never scoped for.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;rotate-like-you-mean-it&quot;&gt;Rotate like you mean it&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#rotate-like-you-mean-it&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Remember the 64 percent of 2022’s leaked secrets that still worked in 2026? Encryption at rest solves the leak. Rotation solves the lifetime.&lt;/p&gt;
&lt;p&gt;Ankra supports rotating the organisation’s AGE key pair from the same Encryption settings page: generate a new pair, re-encrypt existing content with the new public key, confirm, and the old private key is destroyed. Do it on a schedule, and do it when someone with access leaves. The workflow exists so that rotation is an afternoon, not a quarter.&lt;/p&gt;
&lt;p&gt;The same discipline applies to the credentials inside the encrypted files. A database password that has been encrypted in Git for three years is still a three-year-old password. SOPS makes rotation safe to execute through the normal GitOps flow: change the value, the diff shows one key changed, the deploy rolls it out, and the history shows exactly when and by whom.&lt;/p&gt;
&lt;h2 id=&quot;the-five-rules&quot;&gt;The five rules&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-five-rules&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you take nothing else from this post:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Secrets live in Git, encrypted.&lt;/strong&gt; Anywhere else and you have two sources of truth, which is zero sources of truth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Encrypt values, not files.&lt;/strong&gt; Reviews only work when reviewers can read the structure.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;No human touches the private key.&lt;/strong&gt; Initialize once, let the platform hold it, let clusters decrypt automatically.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Plaintext fails the build.&lt;/strong&gt; &lt;code&gt;--strict-secrets&lt;/code&gt; in CI, on every pull request that touches cluster config.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rotate on a schedule, not after an incident.&lt;/strong&gt; Keys quarterly or on departure, credentials on their own clock.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;A GitOps repository where every credential is ciphertext is a repository you can hand to a new hire, an auditor, or an AI agent without holding your breath. That is what the source of truth is supposed to feel like.&lt;/p&gt;
&lt;p&gt;Set it up this afternoon: one click in &lt;a href=&quot;https://docs.ankra.ai/guides/sops&quot;&gt;Organisation Settings, Encryption&lt;/a&gt;, one flag in CI, done.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mattias Åsell</dc:creator><category>Security</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Kubermatic vs Ankra: Do You Want to Run a Kubernetes Factory, or Just Ship Software?</title><link>https://ankra.ai/blog/kubermatic-vs-ankra</link><guid isPermaLink="true">https://ankra.ai/blog/kubermatic-vs-ankra</guid><description>Kubermatic KKP is an open source factory for manufacturing Kubernetes clusters at density, and you are the one who runs the factory. Ankra is the platform your team does not have to operate. An honest comparison from a fellow European vendor.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Kubermatic deserves more recognition than it gets. While American vendors dominate the Kubernetes management conversation, this Hamburg company has been quietly running one of the more technically interesting platforms in the space for the better part of a decade: an open source system that manufactures Kubernetes clusters at a density most competitors cannot match, with an Apache 2.0 community edition you can run without ever talking to sales. When European teams evaluating Ankra ask “why not Kubermatic, it is open source and it is from here,” that is a fair question from people asking the right things.&lt;/p&gt;
&lt;p&gt;The answer has the same shape as our &lt;a href=&quot;/blog/spectro-cloud-vs-ankra&quot;&gt;Spectro Cloud comparison&lt;/a&gt;, but with a twist that matters: Kubermatic Kubernetes Platform (KKP) is a factory for producing and hosting clusters, and you are the one who runs the factory. Ankra is a platform for running what lives on clusters, and nobody on your team operates the platform at all. The real question this post answers is not “which product has more features.” It is: does your organization want to be a Kubernetes provider, or a Kubernetes consumer?&lt;/p&gt;
&lt;h2 id=&quot;what-kkp-actually-is-and-why-the-architecture-is-genuinely-clever&quot;&gt;What KKP actually is, and why the architecture is genuinely clever&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-kkp-actually-is-and-why-the-architecture-is-genuinely-clever&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;KKP is a self-hosted platform for creating and operating fleets of Kubernetes clusters. Its architecture has three tiers: a master cluster holding users, projects, and credentials; seed clusters; and the user clusters your workloads actually run on.&lt;/p&gt;
&lt;p&gt;The seed cluster is the clever part. When KKP creates a user cluster, it does not stand up dedicated control plane VMs. It runs the user cluster’s entire control plane, kube-apiserver, etcd, scheduler, controller-manager, as pods inside a namespace on the seed cluster. One seed hosts the control planes of many user clusters, packed like containers, because they are containers. That density is how KKP credibly claims to manage thousands of clusters: control planes stop being infrastructure you provision and become workloads the seed schedules.&lt;/p&gt;
&lt;p&gt;Around that core, KKP is a complete Kubernetes-as-a-Service operation. It provisions user clusters on AWS, Azure, Google Cloud, OpenStack, vSphere, Nutanix, Hetzner, DigitalOcean, KubeVirt, and edge environments. It ships a self-service portal where project teams create their own clusters from admin-approved templates. It has a one-click multi-tenant monitoring, logging, and alerting stack (Prometheus, Loki, Cortex, Grafana) for user clusters. The 2.30 release from this April added Kubernetes 1.35 support, Gateway API, and better GPU handling for AI workloads. The community edition is genuinely open source under Apache 2.0; the enterprise edition adds multi-seed scaling and support, aimed, in Kubermatic’s own words, at organizations running more than 50 clusters.&lt;/p&gt;
&lt;p&gt;If your organization’s product is Kubernetes itself, a hosting provider selling managed clusters, a telco running network functions, a central IT group offering internal KaaS to forty business units, KKP is one of the best-engineered answers available, and the only major one that is open source top to bottom.&lt;/p&gt;
&lt;h2 id=&quot;the-factory-comes-with-a-factory-floor&quot;&gt;The factory comes with a factory floor&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-factory-comes-with-a-factory-floor&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is the part the architecture diagram does not show: someone has to run all of that, and that someone is you.&lt;/p&gt;
&lt;p&gt;A production KKP deployment means you operate a master cluster, one or more seed clusters (multiple seeds require the enterprise edition), the platform’s own monitoring stack, its upgrades, its certificate rotation, its etcd health for every hosted control plane, and the capacity planning for seeds whose resource needs grow with every user cluster created. KKP’s own documentation is refreshingly honest about this: plan your seed sizing ahead, because control planes are workloads and workloads need somewhere to run.&lt;/p&gt;
&lt;p&gt;None of that is a criticism. It is the deal, stated plainly: KKP transfers the cloud provider’s job to you, and in exchange you get sovereignty, density, and zero per-cluster fees to a hyperscaler. For a service provider, that trade is the business model. For a regulated enterprise that must own everything, the trade is compliance.&lt;/p&gt;
&lt;p&gt;But if you are a product company with six or sixteen clusters, look at what you just signed up for. You now run a platform whose job is to run platforms, staffed by engineers you hired to ship your product. The factory produces clusters beautifully. Someone still has to sweep the factory floor, and the factory does not answer the question you actually had, which was never “how do I get more clusters.”&lt;/p&gt;
&lt;h2 id=&quot;the-question-after-the-cluster-exists&quot;&gt;The question after the cluster exists&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-question-after-the-cluster-exists&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ask the teams we work with what consumed last month, and cluster creation is never on the list. What is on the list: which Helm charts make a cluster production-grade and in what order, why staging drifted from production, &lt;a href=&quot;/blog/clone-production-environments-with-stacks&quot;&gt;how the new developer gets an environment without a ticket&lt;/a&gt;, what broke at 2 AM and which change broke it, where the audit trail is when the auditor asks.&lt;/p&gt;
&lt;p&gt;That is the territory Ankra occupies, and it is territory KKP mostly leaves to you. KKP has addons and an application catalog for seeding user clusters with default tooling, and they work. But the lifecycle of what runs on the cluster, the dependency graph between your applications and their data services, the delivery pipeline, the incident workflow, the review process for changes, that is explicitly your problem in a KKP world, solved with whatever GitOps tooling and observability stack you assemble next to it.&lt;/p&gt;
&lt;p&gt;Ankra’s &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;Stacks&lt;/a&gt; make that lifecycle the platform’s core object: addons, manifests, and applications wired into a dependency graph, deployed in order by &lt;a href=&quot;/blog/native-deployment-engine&quot;&gt;Ankra’s own engine&lt;/a&gt;, with every change from every surface (UI, CLI, API, Terraform, or the AI) written back to your Git repository. The AI on top is an operator, not a workload scheduler: it designs stacks, explains crashing pods against the change that broke them, &lt;a href=&quot;/blog/ai-incident-management&quot;&gt;posts root-cause incident reports to Slack&lt;/a&gt;, and proposes fixes as drafts a human approves. Same contract as always: &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;propose, review, record&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;And the platform itself is not yours to operate. The only thing running in your cluster is the Ankra agent, installed with one Helm command, making outbound connections only. No master cluster, no seeds, no platform monitoring stack, no upgrade weekends. The trade is the mirror image of KKP’s: you give up hosting the management plane, and you get back every hour your team would have spent being its SRE.&lt;/p&gt;
&lt;h2 id=&quot;two-kinds-of-open-honestly-compared&quot;&gt;Two kinds of open, honestly compared&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#two-kinds-of-open-honestly-compared&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kubermatic’s open source credentials are real and deserve respect. KKP CE is Apache 2.0, the repository is public, and you can run the whole platform forever without paying anyone. For teams with a hard open-source-only policy, that settles the evaluation, and it settles it in Kubermatic’s favor.&lt;/p&gt;
&lt;p&gt;Be precise about what the freedom costs and what it protects, though. The freedom is operational: your data, your infrastructure, your hands on every component. The cost is that same sentence read back to you. Free-as-in-freedom software is not free-as-in-headcount, and a production KKP installation is a standing engineering commitment before the first user cluster serves traffic. Meanwhile the features that matter most at the scale where KKP shines, multiple seeds past 50 clusters, are in the paid enterprise edition anyway, so serious fleets end up in a commercial relationship regardless.&lt;/p&gt;
&lt;p&gt;Ankra’s openness runs through a different channel: exit rights rather than source code. Every stack, every value, every dependency lives in your Git repository, written there continuously by the engine. Switch Ankra off tomorrow and you hold a complete, working GitOps description of your entire estate that any tool can reconcile. We made this argument in &lt;a href=&quot;/blog/komodor-vs-ankra&quot;&gt;the Komodor post&lt;/a&gt; and it applies unchanged: the openness that protects you long-term is not being able to read the vendor’s code, it is being able to leave without losing your operational history. Ideally you want both. If you can only have one, take the exit rights.&lt;/p&gt;
&lt;p&gt;On sovereignty, the honest note is that this is shared ground, not a differentiator: Kubermatic is German, Ankra is European too, and neither routes your operations through a US hyperscaler’s control plane. If EU data residency drove you to Kubermatic’s door, it does not argue against Ankra’s.&lt;/p&gt;
&lt;h2 id=&quot;side-by-side&quot;&gt;Side by side&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#side-by-side&quot;&gt;&lt;/a&gt;&lt;/h2&gt;























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dimension&lt;/th&gt;&lt;th&gt;Kubermatic KKP&lt;/th&gt;&lt;th&gt;Ankra&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;What it manufactures&lt;/td&gt;&lt;td&gt;Kubernetes clusters, control planes hosted at density on seeds&lt;/td&gt;&lt;td&gt;Running software: stacks, delivery, operations on any cluster&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Who operates the platform&lt;/td&gt;&lt;td&gt;You: master, seeds, platform MLA, upgrades&lt;/td&gt;&lt;td&gt;Ankra; your side is one outbound agent per cluster&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Deployment model&lt;/td&gt;&lt;td&gt;Self-hosted, on your infrastructure&lt;/td&gt;&lt;td&gt;SaaS platform, agent in your clusters&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Open source&lt;/td&gt;&lt;td&gt;CE under Apache 2.0; EE commercial (multi-seed, 50+ clusters)&lt;/td&gt;&lt;td&gt;Platform is commercial; your config lives in your Git, CLI and agent workflows public&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Source of truth&lt;/td&gt;&lt;td&gt;KKP (CRDs on master/seed; templates in platform)&lt;/td&gt;&lt;td&gt;Your Git repository, written back by the engine&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Delivery of applications&lt;/td&gt;&lt;td&gt;Addons and app catalog; bring your own GitOps&lt;/td&gt;&lt;td&gt;Core product: dependency-graph stacks, drafts, approvals&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AI&lt;/td&gt;&lt;td&gt;GPU and AI workload support for clusters (2.30)&lt;/td&gt;&lt;td&gt;AI operator: designs, investigates, proposes reviewable fixes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sweet spot&lt;/td&gt;&lt;td&gt;Service providers, internal KaaS at fleet scale, sovereignty mandates&lt;/td&gt;&lt;td&gt;Product and platform teams shipping software on Kubernetes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cost of entry&lt;/td&gt;&lt;td&gt;Engineering time to stand up and run the platform&lt;/td&gt;&lt;td&gt;Free 30 worker vCPUs, self-serve, minutes to first import&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;where-kubermatic-is-the-right-call&quot;&gt;Where Kubermatic is the right call&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#where-kubermatic-is-the-right-call&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Same rule as every comparison we publish: there are evaluations Ankra should lose.&lt;/p&gt;
&lt;p&gt;If you sell Kubernetes, as a regional cloud, a managed service provider, or a telco, KKP’s seed architecture is close to purpose-built for your margins: control planes as dense workloads instead of dedicated VMs is a real cost structure advantage at hundreds of clusters. If your mandate is a fully self-hosted, open source management plane inside your own perimeter with no SaaS dependency at all, KKP delivers that and Ankra’s SaaS model does not. If central IT is building an internal cluster vending machine for dozens of autonomous teams and has the platform engineers to staff it, KKP is a mature, honest choice, and you will not resent it.&lt;/p&gt;
&lt;p&gt;And the quiet truth from the Spectro post applies here too: the two are not mutually exclusive. A user cluster minted by KKP is a conformant Kubernetes cluster, and one Helm install of the Ankra agent later it is on Ankra’s graph, with stacks, AI operations, and Git write-back running on top of Kubermatic’s plumbing. The factory makes the cluster. The workshop ships the product. Some organizations legitimately need both floors of that building.&lt;/p&gt;
&lt;h2 id=&quot;the-move&quot;&gt;The move&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-move&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kubermatic answers “how do we produce and host many Kubernetes clusters, ourselves, at density, with open source.” It answers it better than almost anyone. Ankra answers the question that starts the moment a cluster exists and never goes away: “how does this team ship, run, understand, and fix what is on it, without becoming a platform department.”&lt;/p&gt;
&lt;p&gt;If you are staffing a factory, evaluate KKP seriously. If you are trying to get out of running one, &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;create a free account&lt;/a&gt;, import any cluster you already have, KKP-minted ones included, and watch the AI propose its first stack this afternoon. The free 30 vCPU allowance covers the whole experiment.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Comparisons</category><category>Platform Engineering</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>The Early-Stage Infrastructure Playbook: Kubernetes Before Your First DevOps Hire</title><link>https://ankra.ai/blog/kubernetes-for-early-stage-startups</link><guid isPermaLink="true">https://ankra.ai/blog/kubernetes-for-early-stage-startups</guid><description>&apos;Don&apos;t use Kubernetes until you have a platform team&apos; was good advice in 2019. The premises changed. What a two-to-six person company should set up in week one, what to deliberately skip, and what it actually costs: about zero.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There is a piece of advice every technical founder has heard, usually delivered with the weary confidence of someone who has seen things: “Do not touch Kubernetes until you can afford a platform team. Use a PaaS, ship your product, worry about infrastructure later.”&lt;/p&gt;
&lt;p&gt;I want to take that advice seriously, because it was correct when it was coined. Around 2019, adopting Kubernetes as a three-person startup meant one founder becoming a part-time YAML archaeologist: hand-rolling cluster provisioning, assembling ingress and cert-manager and monitoring from blog posts, debugging CrashLoopBackOffs at midnight with nobody to ask. The tax was real, the product suffered, and the PaaS alternative was genuinely the better trade.&lt;/p&gt;
&lt;p&gt;But advice is a compressed conclusion, and conclusions rot when their premises change. Every load-bearing premise under “not yet” has changed. This post is the updated playbook: what an early-stage team should actually set up, what it should refuse to set up, and the math on what it costs, which rounds to zero.&lt;/p&gt;
&lt;h2 id=&quot;what-the-old-advice-was-really-about&quot;&gt;What the old advice was really about&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-the-old-advice-was-really-about&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Strip the meme away and the 2019 advice encoded three true statements:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes itself was expensive to operate.&lt;/strong&gt; Control planes, upgrades, networking, certificates: a standing job before your first deploy.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The ecosystem around it was assembly required.&lt;/strong&gt; Fifteen Helm charts, in the right order, with values nobody documented, glued together by the one person who understood them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Operating it required expertise you could not afford.&lt;/strong&gt; The person who could run it well cost six figures and was better spent building product, if you could hire them at all.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Notice that none of these statements is about Kubernetes being wrong for small workloads. Kubernetes was always a fine way to run a web app, a database, and a queue. The objection was never the destination; it was the price of the road. So the honest question in 2026 is not “is Kubernetes overkill,” it is “what does the road cost now.”&lt;/p&gt;
&lt;h2 id=&quot;what-changed&quot;&gt;What changed&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-changed&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The cluster became a commodity.&lt;/strong&gt; Managed control planes are table stakes on every cloud, and &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;after the Hetzner repricing&lt;/a&gt; we did the math on this blog: a production-shaped cluster on European cloud, three workers, a control plane, ingress, runs about €65 a month. Ankra provisions one on Hetzner, OVHcloud, or UpCloud in minutes, or imports whatever you already have, including the k3s cluster on the OrbStack instance of your laptop. Premise one is gone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The assembly became a product.&lt;/strong&gt; The fifteen-chart scavenger hunt is what &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;Stacks&lt;/a&gt; exist to kill: addons, manifests, and your applications wired into a dependency graph, deployed in order, versioned in Git. Describe the stack once, in the builder or by asking the AI for it, and clone it to every environment you will ever have. Premise two is gone.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The expertise became software.&lt;/strong&gt; This is the one people have not internalized yet. The judgment you were hiring for, which values are load-bearing, why the pod is crashlooping, what that OOM trend means, is exactly what &lt;a href=&quot;/blog/ai-incident-management&quot;&gt;an AI operator with full cluster context&lt;/a&gt; does now: root-cause analysis delivered to Slack, proactive insights before things page you, plain-language explanations of anything on the graph. And because &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;every AI change lands as a draft a human approves and Git records&lt;/a&gt;, you get the senior engineer’s output without handing production to an intern with root. Premise three is the reason this post exists.&lt;/p&gt;
&lt;p&gt;The advice was “not yet” because the road was expensive. The road is now paved, and the toll for a team your size is literally zero: Ankra’s free plan includes 30 worker vCPUs, unlimited clusters, unlimited team members, and the AI, which covers a seed-stage company’s entire footprint with room to spare.&lt;/p&gt;
&lt;h2 id=&quot;but-why-not-just-stay-on-a-paas&quot;&gt;But why not just stay on a PaaS?&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#but-why-not-just-stay-on-a-paas&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Because the PaaS trade has a shape, and early-stage teams keep rediscovering its edges at the worst possible moments.&lt;/p&gt;
&lt;p&gt;The PaaS deal is: pay a premium per compute unit in exchange for not thinking about infrastructure. At day one the premium is small and the not-thinking is priceless, which is why it is a fine place to start and I will not pretend otherwise. The edges show up later, on a schedule you do not control. The pricing curve bends steeply exactly when your usage grows, which is exactly when you have the least time to re-platform. The features you eventually need, a VPC peering, a compliance requirement, a background worker with weird resource needs, a customer who demands EU-only data residency, sit on the other side of a wall the PaaS did not build doors into. And the migration off, when it comes, lands as an unplanned quarter of engineering during your growth phase. Ask anyone who was on Heroku’s free tier in November 2022 how much notice you get when a platform changes its mind.&lt;/p&gt;
&lt;p&gt;Kubernetes through a platform inverts the shape: slightly more thinking on day three, and no wall, ever. The same stack that runs your MVP on one Hetzner node runs your Series B fleet across providers, because the abstraction underneath is the industry’s, not a vendor’s. There is no cliff where you outgrow it, and, as we argued in &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;the cost post&lt;/a&gt;, portability is also the only durable defense against every vendor’s future pricing decisions, PaaS and cloud alike.&lt;/p&gt;
&lt;p&gt;The old model made you choose: PaaS simplicity now and a migration later, or Kubernetes power now and a platform tax later. The entire point of the current generation of tooling is that this fork is gone.&lt;/p&gt;
&lt;h2 id=&quot;the-week-one-playbook&quot;&gt;The week-one playbook&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-week-one-playbook&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is the concrete setup we would give any two-to-six person team, and roughly an afternoon of work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One cluster, boring shape.&lt;/strong&gt; Three CX43 workers and a small control plane on Hetzner through Ankra (about €65 a month), or import the managed cluster your cloud credits pay for. Do not agonize over this choice; the whole point of what follows is that it is cheap to change later.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One GitOps repo from minute one.&lt;/strong&gt; Connect it when you import the cluster. Every change you ever make, from the UI, the CLI, or the AI, becomes a commit. You are two people today and you think you will remember why you changed that value. You will not. In eighteen months, when you hire, the repo is the onboarding doc; in three years, when a customer’s auditor asks, it is the audit trail. This costs nothing to start and cannot be retrofitted.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;One production stack.&lt;/strong&gt; Ingress-nginx, cert-manager, your app, its database, a monitoring addon. Ask the AI to draft it (&lt;code&gt;Cmd+J&lt;/code&gt;, “a production stack for a web app with Postgres, Redis, and TLS on this domain”), review the graph it proposes, deploy. Pin every chart version. Put every secret through &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;SOPS encryption&lt;/a&gt; from day one, because day one is when it is free and day four hundred is when the plaintext password in Git becomes an incident report.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Alerts to the Slack you already live in.&lt;/strong&gt; Wire the webhook so that when something breaks, &lt;a href=&quot;/blog/ai-incident-management&quot;&gt;the message contains a root cause, not a red X&lt;/a&gt;. For a team with no on-call rotation, because the rotation is “both of you,” an alert that arrives pre-investigated is the difference between a five-minute fix and a lost evening.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Environments by cloning, not by ceremony.&lt;/strong&gt; When you need staging, or a demo environment for that enterprise prospect, &lt;a href=&quot;/blog/clone-production-environments-with-stacks&quot;&gt;clone the production stack&lt;/a&gt; and let variables resolve the domains and sizes. The five-person team in that post ran laptop-to-production on this pattern; at your size it is even simpler.&lt;/p&gt;
&lt;p&gt;That is the whole thing. No service mesh, no multi-cluster topology, no platform team, no hire.&lt;/p&gt;
&lt;h2 id=&quot;the-anti-playbook-what-to-refuse-to-build&quot;&gt;The anti-playbook: what to refuse to build&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-anti-playbook-what-to-refuse-to-build&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Early-stage infrastructure fails in two directions, and the second is underrated. Under-engineering gives you the plaintext secret and the untracked hotfix. Over-engineering gives you a three-person company operating a service mesh. Refuse, specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A second cluster you do not need.&lt;/strong&gt; Environments are stacks with different variables, not more control planes. Scale to zero what idles; &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;deleting the Kubernetes layer keeps the config and stops the bill&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A self-hosted observability empire.&lt;/strong&gt; One monitoring addon in the stack. You do not need a Thanos deployment; you barely need &lt;a href=&quot;/blog/prometheus-vs-victoriametrics&quot;&gt;the Prometheus-vs-VictoriaMetrics decision&lt;/a&gt; yet, and when you do, it is a values change, not a project.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A DevOps hire whose job is the platform.&lt;/strong&gt; The moment infrastructure becomes someone’s whole job at a six-person company, a founder has quietly decided to build a platform company inside their product company. Hire when there is product-shaped work for the person, and let the AI hold the pager until then.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A migration you are saving up for.&lt;/strong&gt; The most expensive infrastructure pattern in startups is “we will fix it after the fundraise.” You will not; you will be busier. Start on the thing that does not need leaving.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;the-runway-math-said-out-loud&quot;&gt;The runway math, said out loud&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-runway-math-said-out-loud&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Infrastructure decisions at seed stage are runway decisions wearing overalls. The comparison that matters is not €65 versus €0; it is the fully loaded alternatives:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;The DevOps hire you defer&lt;/strong&gt; is six figures a year in most markets, your single largest line item after founders, spent on someone whose output your customers never see.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The founder-time tax of DIY&lt;/strong&gt; is worse: every hour a technical founder spends debugging ingress annotations at midnight is an hour of the most expensive labor your company will ever employ, spent below its pay grade.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;The PaaS premium plus eventual migration&lt;/strong&gt; is the quiet third option, fine until the invoice bends or the wall appears, both on someone else’s schedule.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Against those: a €65 cluster, a platform whose free tier covers your whole footprint, and an AI that does the investigating. The startup advice canon says do things that do not scale. Your infrastructure is the one place where the same effort now buys you the thing that does.&lt;/p&gt;
&lt;h2 id=&quot;the-unfair-advantage-nobody-mentions&quot;&gt;The unfair advantage nobody mentions&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-unfair-advantage-nobody-mentions&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;One more thing, and it is the one I would actually lead with if this were a pitch instead of a playbook. Early-stage companies do not lose to incumbents on product ideas. They lose on capacity: five people cannot cover product, sales, and a 3 AM pager the way fifty people can. Every hour of operational toil you delete is transferred directly to the only work that differentiates you.&lt;/p&gt;
&lt;p&gt;A five-person team with a senior DevOps agent on call, boring GitOps rails underneath, and infrastructure that clones instead of being rebuilt is not “doing Kubernetes early.” It is competing with a thirty-person company’s operational capacity on a five-person payroll. That is the actual reason the 2019 advice needs retiring: not because Kubernetes got fashionable, but because the leverage flipped sides.&lt;/p&gt;
&lt;p&gt;Start it this weekend. &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account&lt;/a&gt;, import or provision one cluster, ask the AI for your first stack, and connect the Git repo before you deploy anything. Thirty free vCPUs is more infrastructure than most companies need before their Series A, and the setup fits in the afternoon between two customer calls.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mattias Åsell</dc:creator><category>Startups</category><category>Cost Optimization</category><category>AI</category><category>Platform Engineering</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Kubernetes Logging in 2026: Elasticsearch, OpenSearch, Loki, or Just Renting It from Your Cloud</title><link>https://ankra.ai/blog/kubernetes-logging-solutions-compared</link><guid isPermaLink="true">https://ankra.ai/blog/kubernetes-logging-solutions-compared</guid><description>Every logging decision is secretly one question: how much of your log data do you index? A working comparison of Elasticsearch, OpenSearch, Grafana Loki, and cloud services like GCP Logs Explorer, with real pricing math and a decision framework.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Nobody chooses a logging stack. Teams choose a metrics stack deliberately, &lt;a href=&quot;/blog/prometheus-vs-victoriametrics&quot;&gt;argue about it&lt;/a&gt;, benchmark it. Logging just sort of happens: whatever the cloud gives you, or whatever chart someone installed in 2022, quietly ingesting gigabytes a day until the bill or the OOM forces the first real decision. Then the team discovers that logging solutions differ more than almost any other category of infrastructure, and that the differences were all downstream of one question nobody asked at the start.&lt;/p&gt;
&lt;p&gt;The question: &lt;strong&gt;how much of your log data do you index?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Index everything, and every query is instant but you run a search engine cluster. Index almost nothing, and storage is nearly free but queries do the work at read time. Rent the whole problem, and someone else operates it while you pay per gigabyte forever. Every serious option is one of these three answers wearing a product name. Here is the comparison, with the numbers.&lt;/p&gt;
&lt;h2 id=&quot;family-one-index-everything-elasticsearch-and-opensearch&quot;&gt;Family one: index everything (Elasticsearch and OpenSearch)&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#family-one-index-everything-elasticsearch-and-opensearch&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Elasticsearch and OpenSearch are the same answer from two vendors, and their shared story is quick to tell: both are built on Apache Lucene, both tokenize and index every field of every log line at ingest, and both give you the payoff of that work: full-text search across terabytes in milliseconds, arbitrary aggregations, and a mature dashboard layer (Kibana, or OpenSearch Dashboards).&lt;/p&gt;
&lt;p&gt;They split in 2021, when Elastic moved off Apache 2.0 to fight AWS’s managed offering, and AWS forked the last open commit into OpenSearch. Five years on, both halves of the fork are healthy, and the licensing has settled into something you can finally reason about. Elasticsearch (9.4 today) added AGPLv3 back as an option in late 2024, so it is open source again by OSI rules, though the trademark and roadmap remain Elastic’s. OpenSearch (3.7 as of June) is Apache 2.0 under the OpenSearch Software Foundation, part of the Linux Foundation since 2024, with genuinely multi-party governance. If the 2021 fork was about trust, 2026’s honest scorecard says: Elastic rebuilt a lot of it, and OpenSearch built the more neutral home.&lt;/p&gt;
&lt;p&gt;Functionally they remain close enough that choosing between them is mostly a governance and ecosystem question, not a capability one. Elasticsearch moves faster on vendor-led features (ES|QL, the vector search push); OpenSearch has been closing gaps and adding its own (3.7 even ships native PromQL support, of all things).&lt;/p&gt;
&lt;p&gt;What both make you pay is the same tax: &lt;strong&gt;you are now operating a distributed search engine.&lt;/strong&gt; JVM heap sizing, shard strategy, index lifecycle management to tier old indices off hot storage, cluster upgrades, and the RAM appetite that comes from holding an inverted index of everything you have ever logged. The rule of thumb that survives every generation of this stack: the index costs as much as the data. For a Kubernetes cluster logging 50 GB a day, an Elastic-family deployment is typically three dedicated nodes and someone who knows what &lt;code&gt;refresh_interval&lt;/code&gt; does.&lt;/p&gt;
&lt;p&gt;That tax buys real things. If your logs are a product surface (search-heavy support tooling, audit trails a customer queries), if you run security analytics or SIEM workloads over them, or if analysts genuinely ask arbitrary questions of full log content all day, the Elastic family is the correct tool and nothing else on this page truly substitutes for it.&lt;/p&gt;
&lt;h2 id=&quot;family-two-index-almost-nothing-grafana-loki&quot;&gt;Family two: index almost nothing (Grafana Loki)&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#family-two-index-almost-nothing-grafana-loki&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Loki’s founding insight is that most log queries are not arbitrary. An engineer debugging production does not search “all logs containing this string ever.” They look at one service, in one namespace, over the last hour, and then grep. So Loki indexes only a small set of labels (&lt;code&gt;namespace&lt;/code&gt;, &lt;code&gt;app&lt;/code&gt;, &lt;code&gt;pod&lt;/code&gt;, the things you filter by), and stores the log content itself as compressed chunks in object storage. The index is tiny. The storage is S3-priced. The grep happens at query time, brute-forced in parallel over just the chunks your labels selected.&lt;/p&gt;
&lt;p&gt;The consequences, good and bad, all follow from that one design choice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Cost collapses.&lt;/strong&gt; Object storage plus a small index means Loki’s cost per retained terabyte is a fraction of an indexed store’s, and retention becomes a bucket lifecycle policy instead of a cluster expansion.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Kubernetes fit is natural.&lt;/strong&gt; Labels are already how Kubernetes thinks. Your &lt;code&gt;LogQL&lt;/code&gt; query mirrors your &lt;code&gt;kubectl&lt;/code&gt; mental model, and Grafana displays logs next to the metrics they correlate with.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Queries are only as fast as their label selection.&lt;/strong&gt; A well-labeled query over an hour is instant. An unbounded “find this request ID across everything, last 30 days” is a cluster-wide brute-force scan, exactly the query the Elastic family eats for breakfast.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cardinality discipline is mandatory.&lt;/strong&gt; Labels are the index; a high-cardinality label (user ID, request ID) explodes the index and defeats the design. Those values belong in the log line, found by grep, not in labels.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One operational note that matters this year specifically: Promtail, the log shipper most Loki tutorials (ours included) grew up with, reached end-of-life on March 2, 2026. Its replacement is Grafana Alloy, Grafana’s OpenTelemetry Collector distribution, which carries Promtail’s capabilities plus metrics, traces, and OTLP in one agent, and ships a one-command config converter. If you deploy Loki today, deploy Alloy beside it, not Promtail; if you run Promtail today, the migration is a config conversion, not a re-architecture.&lt;/p&gt;
&lt;p&gt;Loki is AGPLv3, single-vendor (Grafana Labs) but with the structural mitigation that your data sits in your object storage in an open format, and the ecosystem around it is the largest in observability.&lt;/p&gt;
&lt;h2 id=&quot;family-three-rent-the-whole-problem-gcp-logs-explorer-and-friends&quot;&gt;Family three: rent the whole problem (GCP Logs Explorer and friends)&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#family-three-rent-the-whole-problem-gcp-logs-explorer-and-friends&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every hyperscaler will make logging entirely not your problem: an agent ships everything to a managed service, retention is a setting, the query UI is a browser tab, and the operational burden is zero. Google’s Cloud Logging with its Logs Explorer is the cleanest example, so let us use its actual prices.&lt;/p&gt;
&lt;p&gt;Cloud Logging charges $0.50 per GiB ingested after a free 50 GiB per project per month, with 30 days of storage included; keeping logs longer costs $0.01 per GiB-month, and querying costs nothing extra. Run the math on a modest 200 GB per month: 150 paid GiB is $75, plus $3 if you keep 90 days. Call it $78 a month for a fully managed, quite good, log system. At 1 TB per month the same math lands around $500. AWS CloudWatch Logs and Azure Monitor price with the same shape: cheap-looking per-GB rates that scale linearly with volume, forever.&lt;/p&gt;
&lt;p&gt;The catches are structural, not hidden. The bill tracks your log volume, and log volume grows with traffic, debug verbosity, and team size, none of which anyone budgets for. The query languages and dashboards are provider-specific, so your runbooks and muscle memory are non-portable. And the moment you have clusters on more than one provider, or &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;on Hetzner where there is no managed logging at all&lt;/a&gt;, you either run two logging systems or none. Cloud logging is the right answer for single-cloud teams below a few hundred gigabytes a month, and it gets quietly wrong as either of those conditions decays.&lt;/p&gt;
&lt;h2 id=&quot;the-same-1-tb-three-ways&quot;&gt;The same 1 TB, three ways&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-same-1-tb-three-ways&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Rough numbers, deliberately conservative, for 1 TB of logs a month with 90-day retention:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Approach&lt;/th&gt;&lt;th&gt;What you run&lt;/th&gt;&lt;th&gt;Monthly cost shape&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;GCP Cloud Logging&lt;/td&gt;&lt;td&gt;Nothing&lt;/td&gt;&lt;td&gt;About $495 ingestion plus $19 retention, roughly $515, scaling linearly with volume forever&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Elasticsearch / OpenSearch&lt;/td&gt;&lt;td&gt;3+ node cluster, ILM, someone who owns it&lt;/td&gt;&lt;td&gt;Roughly $300 to $600 of compute and disk (more on a hyperscaler), plus the real cost: the engineer-hours&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Loki + Alloy&lt;/td&gt;&lt;td&gt;2 small pods plus object storage&lt;/td&gt;&lt;td&gt;Tens of euros of compute, single-digit euros of object storage, cardinality discipline as the price of admission&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The pattern generalizes: cloud logging wins below roughly 100 to 200 GB per month on convenience, Loki wins on cost from there to nearly any scale if your query patterns are label-shaped, and the Elastic family wins whenever the queries themselves are the product, at whatever the cluster costs, because nothing else answers them.&lt;/p&gt;
&lt;h2 id=&quot;the-decision-framework&quot;&gt;The decision framework&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-decision-framework&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Four questions settle almost every case:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Are logs a product or a debugging tool?&lt;/strong&gt; Product (search features, SIEM, customer-facing audit): Elastic family. Debugging: keep reading.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Is all your Kubernetes on one hyperscaler, under ~200 GB per month, and likely to stay that way?&lt;/strong&gt; Yes: use the cloud’s logging, stop here, spend the saved attention elsewhere.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Multi-cloud, cost-sensitive, or European-cloud clusters?&lt;/strong&gt; Loki with Alloy, in your object storage. This is the default answer for most Kubernetes teams in 2026, and it is why it is the default in our stacks too.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Do you need both?&lt;/strong&gt; Common at scale: Loki for the debugging firehose, a small Elastic-family index for the subset that needs real search (security events, audit logs). Route with Alloy; it exists to do exactly this kind of splitting.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;where-ankra-sits-in-this&quot;&gt;Where Ankra sits in this&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#where-ankra-sits-in-this&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Deliberately underneath, and deliberately neutral, the same position as &lt;a href=&quot;/blog/prometheus-vs-victoriametrics&quot;&gt;with metrics backends&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;First: for the most common thing teams use logs for, live debugging, you need none of the above to start. The Ankra agent streams pod logs directly from any managed cluster, and the AI reads them, along with events, manifests, and the stack change that broke things, when it &lt;a href=&quot;/blog/ai-incident-management&quot;&gt;investigates an incident or explains a crashloop&lt;/a&gt;. A logging backend is for retention and search across time, not for “why is this pod crashing right now.” Plenty of small teams run on live logs plus alerts for months, &lt;a href=&quot;/blog/kubernetes-for-early-stage-startups&quot;&gt;which is exactly the right amount of infrastructure for their stage&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;When you do want retention, the logging stack is an ordinary &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;Stack&lt;/a&gt;: Loki and Alloy (or an OpenSearch cluster, if your answer to question one was “product”) as pinned-version addons with the namespace first and dependencies wired through &lt;code&gt;parents&lt;/code&gt;, deployed by &lt;a href=&quot;/blog/native-deployment-engine&quot;&gt;Ankra’s engine&lt;/a&gt;, committed to your Git repo, and &lt;a href=&quot;/blog/clone-production-environments-with-stacks&quot;&gt;cloned to every cluster&lt;/a&gt; that needs it. Grafana credentials and shipper tokens go through &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;SOPS&lt;/a&gt;, because plaintext secrets in a values file is how logging stacks end up in security postmortems.&lt;/p&gt;
&lt;p&gt;The stack is yours to choose. The part where someone has to remember how it was wired, keep it identical across environments, and explain at 3 AM what changed, that part is the platform’s job.&lt;/p&gt;
&lt;p&gt;Pick your family with the framework above, then deploy it once, as a stack, and let it be boring. &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Start free&lt;/a&gt;, and if you are unsure, the AI will happily draft you the Loki stack to react to.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Observability</category><category>Comparisons</category><category>Kubernetes</category><category>DevOps</category></item><item><title>The Kubernetes Security Work That Actually Matters in 2026</title><link>https://ankra.ai/blog/kubernetes-security-that-actually-matters</link><guid isPermaLink="true">https://ankra.ai/blog/kubernetes-security-that-actually-matters</guid><description>Half of all clusters are running an ingress controller that stopped receiving security patches in March. Meanwhile, teams debate service meshes. The five findings that show up in every real cluster security review, each with the incident that proves it and the fix.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In January, the Kubernetes Steering Committee and Security Response Committee published a joint statement with a sentence you rarely see from a project of that size: “Half of you will be affected. You have two months left to prepare.” They were talking about the retirement of ingress-nginx, the controller that routes traffic into roughly half of all cloud native environments. The deadline passed in March. There will be no more releases, no bug fixes, and no security patches, ever, for the component standing between the internet and half the world’s clusters.&lt;/p&gt;
&lt;p&gt;That is what Kubernetes security actually looks like in 2026. Not zero-days in the kubelet, not container escapes from a conference talk. A load-bearing component nobody was paid to maintain, credentials nobody rotates, changes nobody reviews. When we look at real clusters, the same five findings account for nearly all of the actual risk, and none of them are exotic. Here they are, each with the incident that proves it is real and the fix that closes it.&lt;/p&gt;
&lt;h2 id=&quot;finding-1-a-load-bearing-component-nobody-maintains&quot;&gt;Finding 1: A load-bearing component nobody maintains&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#finding-1-a-load-bearing-component-nobody-maintains&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The ingress-nginx story deserves to be told properly, because it is the security lesson of the year. The project served about 50 percent of cloud native environments and was maintained, for years, by one or two people in their free time. In March 2025 that arrangement produced IngressNightmare (CVE-2025-1974), a CVSS 9.8 unauthenticated remote code execution that could hand an attacker the whole cluster. Eight months later the project announced its retirement, and since maintenance ended this March, new vulnerabilities have already been catalogued against a codebase that will never be patched again. Existing deployments keep working, which is precisely the problem: nothing breaks, so nothing forces the migration, so the exposure quietly compounds.&lt;/p&gt;
&lt;p&gt;Check whether this is you, right now:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;kubectl&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;pods&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--all-namespaces&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--selector&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app.kubernetes.io/name=ingress-nginx&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;kubectl get pods --all-namespaces --selector app.kubernetes.io/name=ingress-nginx&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;If that returns pods, you are running retired software on your network edge, and the community’s recommendation is to migrate to Gateway API or another maintained ingress controller. None of the alternatives are drop-in replacements, which is exactly why this belongs at the top of the backlog rather than the bottom.&lt;/p&gt;
&lt;p&gt;The general lesson is bigger than one controller. Your cluster’s security posture is the union of every addon on it, and most teams cannot answer “what versions of what are running where” without an afternoon of kubectl archaeology. This is a place where structure beats vigilance: in Ankra, every addon is a &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;pinned-version node in a stack&lt;/a&gt;, so the inventory question is a glance, the AI’s proactive insights flag vulnerable and end-of-life addon versions before they page you, and the migration itself is a stack change that rolls out &lt;a href=&quot;/blog/native-deployment-engine&quot;&gt;with dependency ordering and a Git record&lt;/a&gt; instead of a hand-run weekend.&lt;/p&gt;
&lt;h2 id=&quot;finding-2-kubeconfigs-are-the-new-ssh-keys-and-they-are-everywhere&quot;&gt;Finding 2: Kubeconfigs are the new SSH keys, and they are everywhere&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#finding-2-kubeconfigs-are-the-new-ssh-keys-and-they-are-everywhere&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ask a team how many valid kubeconfigs exist for their production cluster and watch the faces. There is one on every engineer’s laptop, including two who left last year. There is one in CI, with cluster-admin because scoping it down was a ticket nobody took. There is one in a shared vault whose password is in Slack. Static, long-lived, rarely scoped, never rotated: Kubernetes credentials in most organizations are exactly where SSH keys were in 2010.&lt;/p&gt;
&lt;p&gt;The fix is the same one SSH eventually got: stop distributing static credentials at all. Access should be identity-based, short-lived, and scoped to the task. This is what Ankra’s &lt;a href=&quot;https://docs.ankra.ai/guides/cluster-access&quot;&gt;Cluster Access grants&lt;/a&gt; implement: an admin maps a user to a role (&lt;code&gt;view&lt;/code&gt;, &lt;code&gt;edit&lt;/code&gt;, &lt;code&gt;admin&lt;/code&gt;, &lt;code&gt;cluster-admin&lt;/code&gt;) at a scope (whole cluster or a single namespace), the platform reconciles that grant into native Kubernetes RBAC on the cluster, and the user’s kubectl flows through an authenticated proxy using short-lived tokens minted on demand. Nobody holds a static cluster secret, offboarding is deleting a grant, and the QA lead who needs to check one namespace gets &lt;code&gt;view&lt;/code&gt; on that namespace instead of the keys to production.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;access&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grant&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;sofia@example.com&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--role&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;view&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--namespace&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;staging&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster access grant sofia@example.com --role view --namespace staging&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The same principle applies to the machines: the pipeline agents we wired in &lt;a href=&quot;/blog/building-pipeline-agents-with-ankra-cli&quot;&gt;the CI post&lt;/a&gt; hold one revocable API token, not a kubeconfig, and there is no kubeconfig anywhere in the pipeline to leak.&lt;/p&gt;
&lt;p&gt;And one structural bonus that costs you nothing: the Ankra agent connects outbound only. Importing a cluster requires no inbound firewall rule and no publicly reachable API server, which removes the single most common Kubernetes exposure, the control plane endpoint that Shodan can find, from the board entirely.&lt;/p&gt;
&lt;h2 id=&quot;finding-3-the-secret-is-in-git-and-git-is-forever&quot;&gt;Finding 3: The secret is in Git, and Git is forever&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#finding-3-the-secret-is-in-git-and-git-is-forever&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We wrote a full post on this, &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;Secrets Belong in Git. Plaintext Does Not.&lt;/a&gt;, so here is only the shape: 28.65 million hardcoded secrets landed in public GitHub commits last year, AI-assisted commits leak at roughly double the baseline rate, and the Sisense breach demonstrated what one plaintext credential in one private repo converts into. The fix is SOPS with AGE encryption, initialized once at the organisation level, with &lt;code&gt;--strict-secrets&lt;/code&gt; in CI so a plaintext credential is a failed build instead of a code review comment. If you read nothing else on this list, read that one; secrets remain the most reliably exploited finding on it.&lt;/p&gt;
&lt;h2 id=&quot;finding-4-changes-nobody-reviewed-by-humans-or-their-agents&quot;&gt;Finding 4: Changes nobody reviewed, by humans or their agents&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#finding-4-changes-nobody-reviewed-by-humans-or-their-agents&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most production incidents with a security flavor do not start with an attacker. They start with a change: a values edit applied straight to the cluster, a hotfix kubectl’d in during an incident and never written down, a well-meaning AI agent with production credentials doing something “entirely on its own initiative,” as the PocketOS postmortem memorably put it after an agent destroyed their production database and backups in nine seconds. The 2025 wave of AI-agent incidents, &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;which we dissected when we built our guardrails&lt;/a&gt;, all reduce to the same missing property: no separation between proposing a change and applying it, and no audit trail the actor could not rewrite.&lt;/p&gt;
&lt;p&gt;The fix is a property of your delivery system, not a policy document. Every change, from every surface and every actor, human or AI, goes through the same gate: it lands as a draft or a pull request, a human approves it, and Git records it immutably. In Ankra this is the architecture rather than a convention: the UI, CLI, API, Terraform, and the AI all write through the same engine, the engine writes to Git, and the cluster reconciles from Git. When the auditor asks “who changed the ingress config and who approved it,” the answer is a commit hash, not an interview process. Drift, the gap between what Git says and what the cluster runs, is detected and self-healed by &lt;a href=&quot;/blog/native-deployment-engine&quot;&gt;the engine’s reconcile loop&lt;/a&gt;, so the unreviewed hotfix does not quietly become the new production state.&lt;/p&gt;
&lt;h2 id=&quot;finding-5-latest-is-not-a-version-and-floating-tags-are-a-supply-chain&quot;&gt;Finding 5: &lt;code&gt;latest&lt;/code&gt; is not a version, and floating tags are a supply chain&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#finding-5-latest-is-not-a-version-and-floating-tags-are-a-supply-chain&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every unpinned dependency in your cluster definition is a change you have agreed to accept, sight unseen, at a time of someone else’s choosing. A floating chart version means next week’s deploy installs code nobody reviewed. A &lt;code&gt;latest&lt;/code&gt; image tag means your rollback target is a moving object. The supply chain attacks that make headlines, poisoned packages, hijacked maintainer accounts, all need a victim who auto-ingests updates, and floating versions are the standing invitation.&lt;/p&gt;
&lt;p&gt;The fix costs nothing but discipline: pin exact &lt;code&gt;chart_version&lt;/code&gt; on every addon, immutable tags on every image, so that a Git commit fully determines what runs, and an upgrade is a visible diff that says &lt;code&gt;65.1.1&lt;/code&gt; became &lt;code&gt;66.0.2&lt;/code&gt;, reviewable like any other change. Ankra’s validation checks your cluster definition against your connected registries on every pull request, which turns “does this chart version actually exist where we think it does” into a CI answer instead of a deploy-time surprise.&lt;/p&gt;
&lt;p&gt;While we are here, the honorable mention that nearly made the list: unauthenticated internal dashboards. Researchers found roughly 336,000 Prometheus endpoints facing the public internet in late 2024, leaking credentials and API keys through a tool everyone assumes is behind a firewall. If a human can open your Grafana or Prometheus without authenticating, so can everyone else. (Ankra reads metrics through the agent, so powering &lt;a href=&quot;/blog/prometheus-vs-victoriametrics&quot;&gt;dashboards and AI analysis&lt;/a&gt; requires no publicly exposed endpoint at all.)&lt;/p&gt;
&lt;h2 id=&quot;what-did-not-make-the-list-and-why&quot;&gt;What did not make the list, and why&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-did-not-make-the-list-and-why&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Notice what is absent: service meshes, runtime eBPF sensors, admission controller frameworks, CVE scanners producing four-digit finding counts. Not because those tools are bad, but because they are layer-seven answers bought by teams that have not done the layer-one work. A mesh’s mTLS does not help you when the ingress controller in front of it is unpatched by design, the intern’s kubeconfig is on a stolen laptop, and the database password is in a public repo. Sequence matters. The five findings above are cheaper than any security product, and they close the doors that real incidents actually walked through.&lt;/p&gt;
&lt;p&gt;There is also a pattern across all five worth naming. None of them are fixed by vigilance, training, or a wiki page. All of them are fixed by structure: making the safe path the default path, so the insecure option requires effort rather than the secure one. Pinned versions in a stack, grants instead of kubeconfigs, encryption at save time, drafts before deploys. Security that depends on everyone remembering everything fails on the first busy Friday. Security that is a property of the delivery system does not care how busy Friday gets.&lt;/p&gt;
&lt;h2 id=&quot;the-checklist&quot;&gt;The checklist&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-checklist&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Run these five checks this week; none takes more than an hour:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;kubectl get pods -A --selector app.kubernetes.io/name=ingress-nginx&lt;/code&gt;.&lt;/strong&gt; If it returns pods, migration planning starts today.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Count the valid kubeconfigs for production.&lt;/strong&gt; If the answer is not “zero static ones,” move to grant-based, short-lived access.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;ankra cluster validate -f cluster.yaml --strict-secrets&lt;/code&gt;&lt;/strong&gt; (or grep your repo for &lt;code&gt;password:&lt;/code&gt;). Encrypt what you find, then make the check a CI gate.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pick a recent production change and reconstruct who made it, who approved it, and where that is recorded.&lt;/strong&gt; If the answer involves asking someone, your audit trail is a person.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Grep your cluster definition for &lt;code&gt;latest&lt;/code&gt; and unpinned versions.&lt;/strong&gt; Pin them, and let every future upgrade be a reviewable diff.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Five findings, five checks, and none of them require a security team, which is rather the point: &lt;a href=&quot;/blog/kubernetes-for-early-stage-startups&quot;&gt;a platform that makes them structural&lt;/a&gt; means the five-person company and the fifty-person one pass the same review.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mattias Åsell</dc:creator><category>Security</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>GitOps Without ArgoCD: Inside Ankra&apos;s Native Deployment Engine</title><link>https://ankra.ai/blog/native-deployment-engine</link><guid isPermaLink="true">https://ankra.ai/blog/native-deployment-engine</guid><description>New Ankra clusters no longer run ArgoCD. Here is the engineering story of the native deployment engine: why we built it, how the reconcile loop works, what the migration does to your live resources (nothing), and what we have not finished yet.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;If you created an Ankra cluster after our May 2026 release, there is something missing from it: ArgoCD. No &lt;code&gt;argocd-server&lt;/code&gt;, no repo server, no application controller. Your stacks still deploy, drift still self-heals, SOPS values still decrypt, and Git is still the source of truth. The seven pods that used to do the last mile are simply not there.&lt;/p&gt;
&lt;p&gt;This post is the engineering story behind that change. Not a takedown of ArgoCD, which served us and thousands of our clusters well, but an honest account of what it cost, what we built instead, how the migration adopts your live resources without restarting a single pod, and what the native engine does not do yet.&lt;/p&gt;
&lt;p&gt;The one-sentence version: GitOps is a contract, not a tool. The contract says desired state lives in Git, something reconciles reality against it, and drift gets corrected. Nothing in that contract says the something has to be a seven-pod control plane inside every cluster you operate.&lt;/p&gt;
&lt;h2 id=&quot;what-argocd-was-costing-us&quot;&gt;What ArgoCD was costing us&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-argocd-was-costing-us&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ankra’s engine has always owned the hard parts of delivery: the dependency graph, the ordering, the lifecycle, the Git write-back. ArgoCD’s job in our architecture was narrower than in most shops, essentially the last mile: render the chart, apply it, report health.&lt;/p&gt;
&lt;p&gt;For that last mile, every single cluster carried:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Seven pods.&lt;/strong&gt; &lt;code&gt;argocd-server&lt;/code&gt;, &lt;code&gt;argocd-application-controller&lt;/code&gt;, &lt;code&gt;argocd-repo-server&lt;/code&gt;, &lt;code&gt;argocd-redis&lt;/code&gt;, &lt;code&gt;argocd-applicationset-controller&lt;/code&gt;, &lt;code&gt;argocd-notifications-controller&lt;/code&gt;, and &lt;code&gt;argocd-dex-server&lt;/code&gt;. Roughly 500 to 800 MB of RAM, on every cluster, forever.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;A JWT lifecycle.&lt;/strong&gt; The Ankra agent authenticated to ArgoCD’s API with tokens that had to be created, cached, refreshed, and rotated. An entire class of “deploy failed because auth expired” incidents existed only because of this hop.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;An extra round trip for status.&lt;/strong&gt; Reading addon health meant asking ArgoCD what it thought, over a proxied API call, instead of the agent just knowing.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;On a beefy cloud cluster you can shrug at 800 MB. On the fleets we increasingly see, &lt;a href=&quot;/blog/kubernetes-on-the-edge&quot;&gt;50 warehouse edge nodes&lt;/a&gt;, a k3s cluster on a Raspberry Pi, &lt;a href=&quot;/blog/clone-production-environments-with-stacks&quot;&gt;an OrbStack cluster on a developer laptop&lt;/a&gt;, the overhead tax was often bigger than the workloads. And after &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;June’s Hetzner repricing&lt;/a&gt;, 800 MB of platform overhead per cluster is not an abstraction; it is the difference between a node size.&lt;/p&gt;
&lt;p&gt;There was a subtler cost too. When something went wrong, the answer lived inside ArgoCD’s abstractions. You debugged an &lt;code&gt;Application&lt;/code&gt; CR, sync waves, and a repo server cache, when what you wanted to debug was a Helm release.&lt;/p&gt;
&lt;h2 id=&quot;what-the-native-engine-is&quot;&gt;What the native engine is&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-the-native-engine-is&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The native engine (&lt;code&gt;ankra_native&lt;/code&gt;) deletes the middleman. The Ankra agent, which already runs in every cluster and is already the only writer of cluster state, drives the Helm CLI directly: install, upgrade, reconcile, roll back. No shell interpolation, a single wrapped subprocess with an argument list, one release operation at a time per release, serialised through a Kubernetes Lease.&lt;/p&gt;
&lt;p&gt;The consequence that matters most day to day: releases land in standard Helm storage, the &lt;code&gt;helm.sh/release.v1&lt;/code&gt; Secrets every Helm tool understands. Which means this works, on any Ankra-managed cluster, with no Ankra tooling involved:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;list&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-A&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;history&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-n&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;manifest&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-n&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;rollback&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;4&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-n&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;helm list -Ahelm history grafana -n monitoringhelm get manifest grafana -n monitoringhelm rollback grafana 4 -n monitoring&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Your cluster is debuggable with the ecosystem’s standard tools at 3 AM, even if Ankra’s control plane were unreachable. We consider that a feature on the same tier as any dashboard we could build. There is no proprietary release format, no CR to reverse-engineer, no cache to invalidate. A Helm release is a Helm release.&lt;/p&gt;
&lt;p&gt;The engine is selected per addon, with a cluster-level default. New clusters default to native; existing clusters keep ArgoCD until you choose to migrate. Mixed states are fine and normal, which is exactly what makes the migration boring, in the good way.&lt;/p&gt;
&lt;h2 id=&quot;the-reconcile-loop-concretely&quot;&gt;The reconcile loop, concretely&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-reconcile-loop-concretely&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“We reconcile drift” is easy to say and easy to fake with a timer and a prayer. Here is what the native engine’s sweep actually does, every 60 seconds per cluster:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Recovers stuck releases.&lt;/strong&gt; Any release sitting in a &lt;code&gt;pending-install&lt;/code&gt;, &lt;code&gt;pending-upgrade&lt;/code&gt;, or &lt;code&gt;pending-rollback&lt;/code&gt; state for more than ten minutes, the classic Helm wedge that usually means a human with &lt;code&gt;--force&lt;/code&gt; is coming, gets an automatic fresh &lt;code&gt;helm upgrade --install --atomic&lt;/code&gt;. If that fails, the engine rolls back to the last known &lt;code&gt;deployed&lt;/code&gt; revision.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Detects drift against the rendered truth.&lt;/strong&gt; The live resources are fetched in parallel and diffed against &lt;code&gt;helm get manifest&lt;/code&gt;, with Helm-injected metadata stripped from both sides so you are comparing intent against reality, not annotation noise.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Self-heals when told to.&lt;/strong&gt; If drift is found and the addon’s &lt;code&gt;sync_policy.self_heal&lt;/code&gt; is on, the addon is marked for update and the reconciler re-runs the upgrade. Someone’s manual &lt;code&gt;kubectl edit&lt;/code&gt; quietly stops being the state of production.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Prunes orphans when told to.&lt;/strong&gt; With &lt;code&gt;auto_prune&lt;/code&gt; enabled, resources whose UID is no longer in the rendered manifest are deleted after apply, so removed chart resources do not accumulate as archaeology.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Proves it is alive.&lt;/strong&gt; Every sweep publishes a heartbeat with the sweep duration and the number of addons inspected, and the platform exposes a reconcile-loop lag metric per cluster. A reconciler you cannot monitor is a reconciler you get to discover has been dead for a week.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Sync windows survived the migration from ArgoCD too: give an addon a cron expression, a duration, and a timezone, and create, update, and self-heal operations only run inside the window. Outside it, the job returns immediately as cancelled with an explicit “outside sync window” message rather than silently queueing into your Friday evening.&lt;/p&gt;
&lt;h2 id=&quot;feature-parity-honestly&quot;&gt;Feature parity, honestly&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#feature-parity-honestly&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;We held the migration until the answer to “what do I lose?” was almost nothing:&lt;/p&gt;




























































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Capability&lt;/th&gt;&lt;th&gt;ArgoCD engine&lt;/th&gt;&lt;th&gt;Native engine&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Self-heal on drift&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes, per-addon &lt;code&gt;sync_policy.self_heal&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prune orphaned resources&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes, &lt;code&gt;auto_prune&lt;/code&gt; plus post-apply orphan sweep&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Ignore-differences rules (JSON pointers, jq paths, field managers)&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sync windows&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes, cron plus duration plus timezone&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Custom retry policy&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Strict health checks&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Revision history limit&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes, &lt;code&gt;--history-max&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SOPS-encrypted values&lt;/td&gt;&lt;td&gt;Yes, via helm-secrets plugin&lt;/td&gt;&lt;td&gt;Yes, direct &lt;code&gt;sops --decrypt&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;GitHub, Bitbucket Cloud, Bitbucket DC&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Multi-source applications&lt;/td&gt;&lt;td&gt;Yes&lt;/td&gt;&lt;td&gt;Not yet, single source only&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;The SOPS row deserves a sentence, because it connects to &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;the secrets post&lt;/a&gt;. Under ArgoCD, decryption ran through the helm-secrets plugin on the repo server, with the AGE key deployed to the cluster as a Kubernetes Secret. Under the native engine, the agent fetches the encrypted values file from your Git provider, pulls the key from the platform for just that render, runs &lt;code&gt;sops --decrypt&lt;/code&gt; itself, and hands Helm the plaintext. The private key is never stored on the cluster; it exists in a locked-down temporary file for the seconds the decryption takes and is deleted immediately after. Fewer places a key exists is the whole game in secrets management, and this removed one.&lt;/p&gt;
&lt;p&gt;One honest limitation on that path: today the native engine decrypts the values file referenced by the addon’s configuration. If you split encrypted values across several files on one addon, consolidate them into that file, or keep that addon on the ArgoCD engine until multi-file support lands.&lt;/p&gt;
&lt;h2 id=&quot;the-migration-adoption-not-reinstallation&quot;&gt;The migration: adoption, not reinstallation&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-migration-adoption-not-reinstallation&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The part everyone fears about switching deployment engines is the switch. Here is what per-addon migration actually does:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;upgrade&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--install&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--take-ownership&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;helm upgrade --install --take-ownership&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Helm’s take-ownership flow adopts the live resources into Helm storage. Resource UIDs do not change. No pod is recreated. No traffic blips. The only on-cluster mutation is metadata: the &lt;code&gt;app.kubernetes.io/managed-by=Helm&lt;/code&gt; label and the release-name and release-namespace annotations. The ArgoCD &lt;code&gt;Application&lt;/code&gt; CR is deleted only after the Helm release verifies as &lt;code&gt;deployed&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Before anything runs, the platform shows a per-addon eligibility report: addons whose live resources include kinds the native health rules do not cover yet get flagged, in-flight ArgoCD syncs block until they settle, and multi-source applications are marked not yet migratable. The migration runs per addon, in parallel up to a small concurrency limit, and is resumable across control-plane restarts. Until you explicitly decommission ArgoCD on the cluster, any individual addon can be rolled back to the ArgoCD engine.&lt;/p&gt;
&lt;p&gt;And when the last addon has migrated, decommissioning deliberately stops short of uninstalling ArgoCD. Plenty of teams run their own application delivery through the same ArgoCD instance, outside of Ankra’s addons. We clear our managed credentials and step away. Your ArgoCD, your call.&lt;/p&gt;
&lt;h2 id=&quot;why-this-matters-beyond-the-ram&quot;&gt;Why this matters beyond the RAM&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#why-this-matters-beyond-the-ram&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The resource savings are real but they are the least interesting part.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Debuggability became standard.&lt;/strong&gt; Every question about a deployment now has a &lt;code&gt;helm&lt;/code&gt; answer. Your existing runbooks, your muscle memory, your incident tooling all apply. The abstraction between you and your releases went from “a CD system’s data model” to “the package manager you already use.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The failure surface shrank.&lt;/strong&gt; Every component in the delivery path is a component that can be the incident. Removing the ArgoCD hop removed its API, its tokens, its Redis, and its cache from the list of things that can be why production did not update.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The contract stayed identical.&lt;/strong&gt; This is the point I care most about. Stacks, drafts, approvals, the dependency graph, Git write-back, &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;the AI’s propose-review-record mandate&lt;/a&gt;, none of it changed, because none of it ever lived in ArgoCD. It lives in Ankra’s engine and in your repository. Swapping the last-mile executor under a well-defined contract is exactly the kind of change a platform should be able to make without its users rewriting anything. That it shipped as a settings-page button rather than a migration project is the architecture working as intended.&lt;/p&gt;
&lt;p&gt;If you run new clusters, you are already on the native engine and there is nothing to do. If you have existing clusters on ArgoCD, the &lt;strong&gt;Migrate to native engine&lt;/strong&gt; button is in your cluster settings, the eligibility report will tell you if anything needs attention first, and the &lt;a href=&quot;https://docs.ankra.ai/concepts/deployment-engines&quot;&gt;deployment engines documentation&lt;/a&gt; covers the details.&lt;/p&gt;
&lt;p&gt;Seven fewer pods per cluster, one fewer credential lifecycle, zero fewer guarantees.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mattias Åsell</dc:creator><category>Engineering</category><category>GitOps</category><category>Platform Engineering</category><category>Kubernetes</category></item><item><title>Prometheus vs VictoriaMetrics: When the Default Stops Being the Answer</title><link>https://ankra.ai/blog/prometheus-vs-victoriametrics</link><guid isPermaLink="true">https://ankra.ai/blog/prometheus-vs-victoriametrics</guid><description>Prometheus is the right first monitoring stack for almost everyone, and the wrong last one for a growing minority. An honest comparison of the two, the cardinality wall that forces the question, and how to run either (or both) on Ankra.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Every Kubernetes cluster we see starts its monitoring life the same way: kube-prometheus-stack, Grafana, a dashboard someone found on the internet, done. That is the correct starting move. It is also why, a year or two later, we keep having the same conversation with teams whose Prometheus has started eating 40 GB of RAM, restarting into half-hour WAL replays, or getting OOM-killed the day a deploy added one innocent-looking label.&lt;/p&gt;
&lt;p&gt;That conversation is usually titled “should we move to VictoriaMetrics?” and the answer is a genuine “it depends,” which is the most annoying answer in engineering unless someone tells you exactly what it depends on. That is this post. Ankra has no horse in this race: the platform reads metrics from any Prometheus-compatible endpoint, and both systems deploy as ordinary stacks. What follows is the comparison we walk customers through, with the numbers and the failure stories that inform it.&lt;/p&gt;
&lt;h2 id=&quot;what-prometheus-gets-right-still&quot;&gt;What Prometheus gets right, still&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-prometheus-gets-right-still&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let us start by being fair to the incumbent, because it earned its position.&lt;/p&gt;
&lt;p&gt;Prometheus is the second project ever to graduate from the CNCF, after Kubernetes itself. Its governance is multi-vendor, its ecosystem is the industry’s shared vocabulary, and its integration with Kubernetes is not “good,” it is the reference: the Prometheus Operator’s &lt;code&gt;ServiceMonitor&lt;/code&gt;, &lt;code&gt;PodMonitor&lt;/code&gt;, and &lt;code&gt;PrometheusRule&lt;/code&gt; CRDs are the most battle-tested way to wire scraping that exists. Every exporter targets it. Every alerting example assumes it. PromQL is the lingua franca that every competing backend, VictoriaMetrics included, must speak to be taken seriously.&lt;/p&gt;
&lt;p&gt;And it has not stood still. The 3.x line (3.0 shipped in late 2024; 3.13 landed this month) brought a native OTLP receiver so OpenTelemetry metrics land without a collector in between, full UTF-8 metric and label names so OTel-style names no longer get mangled with underscores, and native histograms, stable since 3.8, which replace dozens of bucket series with a single efficient exponential histogram. The old benchmark gaps you find in blog posts from 2020 have narrowed with every release since.&lt;/p&gt;
&lt;p&gt;For a single cluster with tens or a few hundreds of thousands of active series, Prometheus with 15 to 30 days of retention is boring, well-understood, and correct. If that describes you, you can stop reading and keep your stack. There is no prize for migrating a healthy system.&lt;/p&gt;
&lt;h2 id=&quot;the-wall-and-why-it-is-always-cardinality&quot;&gt;The wall, and why it is always cardinality&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-wall-and-why-it-is-always-cardinality&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Prometheus keeps every active time series in an in-memory head block at a cost of roughly 3 to 4 KB of RAM per series. That is the single number that explains most Prometheus incidents: a million active series is several gigabytes of RAM before anyone runs a query. Every unique combination of label values is its own series. Attach a label with unbounded values, a user ID, a request path, a pod name in a high-churn deployment, and the series count multiplies silently.&lt;/p&gt;
&lt;p&gt;The failure mode is not graceful degradation. It is the OOM killer, followed by a write-ahead-log replay on restart that can take tens of minutes while you have no monitoring at all. This is not a small-team skill issue. Cloudflare maintains custom patches on their 900-plus Prometheus fleet because upstream has no hard cap on series count. The UK Ministry of Justice’s cloud platform lost monitoring for over three hours in 2024 when a WAL replay outran the startup probe and put Prometheus into a restart loop. Teams running Prometheus on machines with hundreds of gigabytes of RAM have still hit the ceiling.&lt;/p&gt;
&lt;p&gt;You can hold the wall back with discipline: recording rules, relabeling to drop offending labels, &lt;code&gt;sample_limit&lt;/code&gt; per target, federation to shard the load. Plenty of teams do. But notice what you are doing: operating around the storage engine’s design, forever. At some scale, the question stops being “how do we tune Prometheus” and becomes “should the thing we tune be something else.”&lt;/p&gt;
&lt;h2 id=&quot;what-victoriametrics-actually-changes&quot;&gt;What VictoriaMetrics actually changes&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-victoriametrics-actually-changes&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;VictoriaMetrics is an Apache 2.0 time-series database built to be a drop-in Prometheus replacement: it scrapes the same targets with the same configs, serves the same HTTP query API so Grafana’s Prometheus datasource works unchanged, and accepts Prometheus &lt;code&gt;remote_write&lt;/code&gt;. The differences are under the floor.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The storage engine.&lt;/strong&gt; Instead of a WAL plus in-memory head block plus two-hour compacted blocks, VictoriaMetrics uses a MergeTree-inspired design closer to ClickHouse. The practical consequences: no WAL replay on restart, no compaction I/O spikes, and much tighter compression. When series churn exceeds what fits in memory, ingestion slows down (visible in a metric you can alert on) rather than the process dying. Running out of headroom becomes a dial you watch instead of a page you get.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The resource profile.&lt;/strong&gt; Here honesty is required, because most published benchmarks come from the vendor. VictoriaMetrics’ own 2024 comparison showed 2.5x less disk and 1.7x less RAM than Prometheus on identical workloads; the older “7x less disk” figures trace to a 2020 test against a long-obsolete Prometheus and should be retired. The credible independent evidence points the same direction with workload-dependent magnitude: Criteo, running around a billion active series, reported roughly one byte per datapoint in production and cut their metrics backend from 382 nodes to 61 while storing 15 times more data. Prezi went on record with a 70 percent storage reduction, 60 percent less memory, and heavy queries dropping from over 30 seconds to single digits after moving 5 million series off Prometheus. The rule of thumb that survives contact with reality: budget about 1 GB of RAM per million active series for VictoriaMetrics against several for Prometheus.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The scaling story.&lt;/strong&gt; A single VictoriaMetrics binary comfortably handles millions of active series, and past that there is a cluster version with horizontal scaling and replication set by one flag. Which brings us to the comparison people actually get wrong.&lt;/p&gt;
&lt;h2 id=&quot;the-real-comparison-is-not-prometheus-vs-victoriametrics&quot;&gt;The real comparison is not Prometheus vs VictoriaMetrics&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-real-comparison-is-not-prometheus-vs-victoriametrics&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;For anything beyond one cluster and a few weeks of retention, plain Prometheus is not the alternative, because plain Prometheus does not do high availability, global views, or years of retention at all. The honest comparison is Prometheus plus Thanos or Mimir versus VictoriaMetrics, and that changes the calculus entirely.&lt;/p&gt;
&lt;p&gt;The Prometheus path to durability means running replica pairs per cluster, sidecars or remote writes shipping blocks to object storage, compactors, store gateways, and query frontends that deduplicate across replicas. Thanos and Mimir are both capable, proven systems. They are also each a distributed system you now operate on top of your monitoring, with their own failure modes, upgrade cycles, and 2 AM personalities.&lt;/p&gt;
&lt;p&gt;VictoriaMetrics answers the same requirements inside one system: retention is a flag, replication is a flag, deduplication is a flag, and multi-year storage rides on the same compressed local disks. Criteo’s numbers above came from evaluating exactly this three-way choice. When teams tell us they want “Prometheus but durable,” a large part of the answer is deciding whether they want to assemble that from parts or get it in one box.&lt;/p&gt;
&lt;h2 id=&quot;promql-vs-metricsql-the-fine-print&quot;&gt;PromQL vs MetricsQL, the fine print&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#promql-vs-metricsql-the-fine-print&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;VictoriaMetrics queries with MetricsQL, a deliberate superset of PromQL. Nearly all existing queries and Grafana dashboards run unchanged, which is why migrations rarely break dashboards. It adds genuinely useful things: &lt;code&gt;WITH&lt;/code&gt; expressions for reusable query fragments, extra rollup functions, the &lt;code&gt;keep_metric_names&lt;/code&gt; modifier.&lt;/p&gt;
&lt;p&gt;But “superset” hides deliberate divergence. In the independent PromLabs compliance suite, VictoriaMetrics scored 74 percent, against 100 for Thanos and Mimir. Most failures are intentional choices the VictoriaMetrics authors consider more correct: &lt;code&gt;rate()&lt;/code&gt; and &lt;code&gt;increase()&lt;/code&gt; consider the sample just before the window, NaN handling differs, metric names survive some functions that strip them in Prometheus. In day-to-day dashboarding you will likely never notice. Where it bites is precision work: a large library of recording rules and alerts tuned to Prometheus’ exact extrapolation behavior may fire differently after a migration, and alert thresholds deserve a review pass. If strict PromQL portability across backends is a hard requirement for you, that is a legitimate reason to stay in the Prometheus family.&lt;/p&gt;
&lt;h2 id=&quot;governance-because-it-matters-now&quot;&gt;Governance, because it matters now&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#governance-because-it-matters-now&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The last two years taught everyone to read licenses before adopting infrastructure. Prometheus is CNCF-owned, multi-vendor, and structurally impossible for any one company to capture. VictoriaMetrics is one bootstrapped company of about 50 people, with an enterprise tier alongside the open core.&lt;/p&gt;
&lt;p&gt;That asymmetry is real but smaller than it looks. VictoriaMetrics’ open source is Apache 2.0 and the project takes no contributor license agreement, meaning contributors keep their copyright and the existing code cannot be relicensed out from under you the way HashiCorp’s and Redis’s licenses were changed. The realistic risk is not a rug-pull; it is future features landing enterprise-first. Adopt with eyes open, as with any single-vendor dependency.&lt;/p&gt;
&lt;h2 id=&quot;the-decision-compressed&quot;&gt;The decision, compressed&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-decision-compressed&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Stay on (or start with) Prometheus when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;One or a few clusters, series counts in the low hundreds of thousands, retention needs measured in weeks&lt;/li&gt;
&lt;li&gt;Your organisation requires CNCF-governed, vendor-neutral tooling&lt;/li&gt;
&lt;li&gt;You maintain recording rules and alerts whose exact PromQL semantics are load-bearing&lt;/li&gt;
&lt;li&gt;Your stack is healthy today; migrating a working system is a cost with no benefit&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Move to (or start with) VictoriaMetrics when:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Prometheus RAM or OOM incidents are a recurring agenda item&lt;/li&gt;
&lt;li&gt;You need one queryable view over many clusters, the exact fleet problem we described in &lt;a href=&quot;/blog/kubernetes-on-the-edge&quot;&gt;the edge post&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;You want months or years of retention without operating Thanos or Mimir alongside&lt;/li&gt;
&lt;li&gt;You are paying for monitoring nodes and the 1 GB versus several GB per million series difference is a real invoice line, which after &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;June’s Hetzner repricing&lt;/a&gt; it is&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And remember the third option, which is where most successful migrations start: both. Add VictoriaMetrics as a &lt;code&gt;remote_write&lt;/code&gt; target from your existing Prometheus, point long-range dashboards at it, and let the two run side by side until the cutover is a formality instead of a bet:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;prometheus.yml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;remote_write&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;url&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;http://victoria-metrics.monitoring.svc.cluster.local:8428/api/v1/write&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;remote_write:  - url: http://victoria-metrics.monitoring.svc.cluster.local:8428/api/v1/write&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;running-either-on-ankra&quot;&gt;Running either on Ankra&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#running-either-on-ankra&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Whichever way you decide, the mechanics on Ankra are the same, because both are just addons in a &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;stack&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The classic stack is kube-prometheus-stack plus Loki and Promtail, with the namespace deployed first and dependencies wired through &lt;code&gt;parents&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;stacks&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;manifests&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring-ns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from_file&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;manifests/monitoring-namespace.yaml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;addons&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;kube-prometheus-stack&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;chart_name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;kube-prometheus-stack&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;chart_version&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;65.1.1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;repository_url&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;https://prometheus-community.github.io/helm-charts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;parents&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;manifest&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring-ns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;configuration&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from_file&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;values/kube-prometheus-stack.yaml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;encrypted_paths&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;adminPassword&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;stacks:  - name: monitoring    manifests:      - name: monitoring-ns        from_file: &amp;quot;manifests/monitoring-namespace.yaml&amp;quot;    addons:      - name: kube-prometheus-stack        chart_name: kube-prometheus-stack        chart_version: 65.1.1        repository_url: https://prometheus-community.github.io/helm-charts        namespace: monitoring        parents:          - manifest: monitoring-ns        configuration:          from_file: &amp;quot;values/kube-prometheus-stack.yaml&amp;quot;          encrypted_paths:            - adminPassword&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Swap the addon for &lt;code&gt;victoria-metrics-single&lt;/code&gt; (or the cluster chart) from the VictoriaMetrics Helm repository and the shape of the stack does not change. Pin the chart version, keep the Grafana admin password &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;SOPS-encrypted&lt;/a&gt;, and clone the same stack to every cluster that needs it.&lt;/p&gt;
&lt;p&gt;Then point the platform at whichever backend you chose. Ankra’s metrics integration accepts any Prometheus-compatible query endpoint, and that compatibility is exactly why this choice is low-stakes at the platform layer:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Backend&lt;/th&gt;&lt;th&gt;Endpoint you connect&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Prometheus (kube-prometheus-stack)&lt;/td&gt;&lt;td&gt;&lt;code&gt;http://prometheus-operated.monitoring.svc.cluster.local:9090&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;VictoriaMetrics&lt;/td&gt;&lt;td&gt;&lt;code&gt;http://victoria-metrics.monitoring.svc.cluster.local:8428&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Thanos Query&lt;/td&gt;&lt;td&gt;&lt;code&gt;http://thanos-query.monitoring.svc.cluster.local:9090&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Grafana Cloud, Amazon or Google managed Prometheus&lt;/td&gt;&lt;td&gt;the provider’s query URL plus a read-only credential&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;That one setting feeds the resource graphs on every pod and deployment, the cluster dashboards, and, most importantly, the AI. When &lt;a href=&quot;/blog/ai-incident-management&quot;&gt;an incident report lands in Slack&lt;/a&gt; or the assistant explains why a pod is throttling, the metrics behind that analysis come from this data source. The AI does not care whether &lt;code&gt;container_memory_working_set_bytes&lt;/code&gt; came out of Prometheus or VictoriaMetrics. It cares that the query answers quickly, which, if you have just moved a multi-million-series fleet to VictoriaMetrics, it now does.&lt;/p&gt;
&lt;p&gt;Pick the engine for your scale, not for fashion. Prometheus by default, VictoriaMetrics when the default starts costing you sleep or servers, and either way the platform on top does not change.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Observability</category><category>Comparisons</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Spectro Cloud vs Ankra: Managing the Metal, or Running What Lives On It?</title><link>https://ankra.ai/blog/spectro-cloud-vs-ankra</link><guid isPermaLink="true">https://ankra.ai/blog/spectro-cloud-vs-ankra</guid><description>Spectro Cloud&apos;s Palette is a serious enterprise platform for provisioning Kubernetes estates from the OS up. Ankra is an AI-native platform for running everything that happens on Kubernetes from the app down. The honest comparison, including when Palette is the right call.</description><pubDate>Sat, 04 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Spectro Cloud is a serious company. Palette manages Kubernetes estates for telcos, defense agencies, and manufacturers, it closed a $75 million Series C led by Goldman Sachs’ growth equity arm in late 2024, and it reported doubling revenue the year after. When teams evaluating Ankra ask “how do you compare to Spectro Cloud,” they are asking about a real platform with real customers, and it deserves a real answer rather than a feature-table ambush.&lt;/p&gt;
&lt;p&gt;Here is the real answer: Spectro Cloud and Ankra look similar from a distance, both are “manage all your Kubernetes from one place” platforms with agents in your clusters and blueprint concepts at the core, but they point in opposite directions. Palette manages Kubernetes downward: the distro, the operating system underneath it, the bare metal and hypervisors underneath that. Ankra runs Kubernetes upward: the addons, the applications, the delivery, the incidents, the developers, and the AI that operates all of it. Which direction you need is the whole decision, and for a lot of readers the honest conclusion will be that they need one of these platforms and not the other.&lt;/p&gt;
&lt;p&gt;Let us take it apart properly.&lt;/p&gt;
&lt;h2 id=&quot;what-palette-actually-is&quot;&gt;What Palette actually is&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-palette-actually-is&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Palette is a full-lifecycle Kubernetes management platform built around two ideas.&lt;/p&gt;
&lt;p&gt;The first is the &lt;strong&gt;Cluster Profile&lt;/strong&gt;: a declarative, layered blueprint of an entire cluster, and “entire” means further down than most tools go. A profile stacks the operating system, the Kubernetes distribution, the CNI and CSI layers, and add-on applications into one versioned object. Palette then builds clusters from that profile and holds them to it. It extends the CNCF Cluster API project for the provisioning machinery, which is the architecturally sound way to do it.&lt;/p&gt;
&lt;p&gt;The second is &lt;strong&gt;breadth of substrate&lt;/strong&gt;. Palette provisions and manages clusters on AWS, Azure, and Google Cloud (both IaaS and the managed EKS, AKS, GKE services), on VMware vSphere, Nutanix, and Apache CloudStack in the data center, on bare metal through Canonical MAAS, and on edge devices, including air-gapped ones. There is a hardened FIPS-compliant edition for government, a Virtual Machine Orchestrator for running VMs next to containers as a VMware exit ramp, and since late 2025 there is PaletteAI, a platform for deploying NVIDIA AI factory infrastructure, GPUs, DPUs, NIM, NeMo and all, from data center to edge.&lt;/p&gt;
&lt;p&gt;If your problem is “I have three data centers full of vSphere, a bare-metal footprint, four hundred retail edge boxes, and a mandate to run Kubernetes on all of it with the OS lifecycle under management,” Palette is one of a very small number of credible answers to that problem. I want to be unambiguous about that before the comparison, because the rest of this post is about a different problem.&lt;/p&gt;
&lt;h2 id=&quot;the-different-problem&quot;&gt;The different problem&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-different-problem&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Walk into the teams we work with, &lt;a href=&quot;/blog/clone-production-environments-with-stacks&quot;&gt;the five-person product team&lt;/a&gt;, the platform team of a mid-size SaaS, the agency running client workloads, and ask what actually hurts. It is almost never “we cannot provision the operating system.” Their clusters come from EKS, from Hetzner, from k3s on a box, from OrbStack on a laptop. The cluster is a commodity, increasingly the cheapest line on the invoice, as we worked through &lt;a href=&quot;/blog/kubernetes-cost-after-hetzner-price-hike&quot;&gt;after the Hetzner repricing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;What hurts is everything above the cluster. Which fifteen Helm charts make it production-grade, in which order, with which values. Who is allowed to change them and how the change is reviewed. What happens at 2 AM when a pod crashloops and the one person who understands cert-manager is asleep. How a developer gets a production-like environment without filing a ticket. Where the audit trail lives when the auditor asks.&lt;/p&gt;
&lt;p&gt;That is the problem Ankra is built for, and it shapes every architectural choice differently than Palette’s problem shaped theirs.&lt;/p&gt;
&lt;h2 id=&quot;blueprints-cluster-profiles-vs-stacks&quot;&gt;Blueprints: Cluster Profiles vs Stacks&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#blueprints-cluster-profiles-vs-stacks&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Both platforms have a blueprint at the center, and comparing them is the fastest way to see the philosophical split.&lt;/p&gt;
&lt;p&gt;A Palette Cluster Profile answers: what should this cluster be? OS, distro, CNI, monitoring agents, security tooling, baked into layers, enforced by the agent. Its natural owner is an infrastructure team, its natural scope is the fleet, and its natural cadence is quarterly. It is infrastructure-as-catalog, and at fleet scale that governance is exactly what a central IT organization wants.&lt;/p&gt;
&lt;p&gt;An Ankra &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;Stack&lt;/a&gt; answers: what should run on this cluster, and in what order? Helm addons, raw manifests, applications, and the dependency edges between them, rendered as a visible graph with deploy order, namespaces, and ingress paths on display before anything ships. Its natural owner is whoever ships the software, its natural scope is a solution (a monitoring stack, a data layer, a product), and its natural cadence is daily. Variables resolve per cluster so one stack template lands correctly in dev, staging, production, and a laptop. Stacks clone across clusters and organisations as drafts, &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;with secrets deliberately left behind&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The tell is what each blueprint refuses to model. Cluster Profiles do not model the dependency choreography between your applications and their data services; that is your CD tool’s job in a Palette world. Stacks do not model the operating system under the kubelet; Ankra assumes something else owns the metal, whether that is AWS, Hetzner via &lt;a href=&quot;https://docs.ankra.ai/guides/hetzner-clusters&quot;&gt;Ankra’s own provisioning&lt;/a&gt;, or your data center team.&lt;/p&gt;
&lt;h2 id=&quot;git-written-back-or-managed-through-an-api&quot;&gt;Git: written back, or managed through an API&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#git-written-back-or-managed-through-an-api&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Palette is operated through its UI, API, and a solid Terraform provider. Profiles and cluster specs are Palette objects, versioned and governed inside Palette. You can wire GitOps tooling into what Palette deploys, but the platform’s source of truth is the platform.&lt;/p&gt;
&lt;p&gt;Ankra inverts that. Every change, from the UI, the CLI, the API, Terraform, or the AI, is written back to your Git repository as commits and pull requests, and the engine reconciles from Git. This is the same argument we made &lt;a href=&quot;/blog/komodor-vs-ankra&quot;&gt;in the Komodor comparison&lt;/a&gt;, and it is worth repeating in one sentence because it is the highest-stakes line in any platform evaluation: if you switch Ankra off tomorrow, you keep a complete, working GitOps repository describing every stack, every value, and every dependency, and your workloads keep running. Your operational history accumulates in an asset you own, not in a vendor’s database.&lt;/p&gt;
&lt;p&gt;At enterprise fleet scale, Palette’s model is a governance feature: profiles as controlled catalog items, drift as a violation. At product-team scale, it is a second source of truth to keep synchronized with the one your developers already live in. Which one is right depends entirely on which team you are.&lt;/p&gt;
&lt;h2 id=&quot;two-meanings-of-ai-platform&quot;&gt;Two meanings of “AI platform”&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#two-meanings-of-ai-platform&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Both companies say AI a lot in 2026. They mean almost entirely different things, and this is the least understood difference between them.&lt;/p&gt;
&lt;p&gt;PaletteAI is a platform &lt;strong&gt;for deploying AI workloads&lt;/strong&gt;. It packages NVIDIA’s AI Enterprise stack, provisions GPUs and DPUs, applies validated AI factory designs, and gets an inference environment running in hours instead of months. The AI is the cargo. It is a smart bet on where enterprise infrastructure spend is going, and if you are standing up NVIDIA racks, it is genuinely relevant.&lt;/p&gt;
&lt;p&gt;Ankra’s AI is &lt;strong&gt;an operator of your platform&lt;/strong&gt;. It designs stacks with you in the Stack Builder, explains a crashing pod against its logs, events, and the stack change that broke it, &lt;a href=&quot;/blog/ai-incident-management&quot;&gt;investigates incidents and posts root causes to Slack&lt;/a&gt;, scans clusters continuously for drift and capacity risks, and proposes fixes as reviewable drafts under the &lt;a href=&quot;/blog/drafts-approvals-gitops&quot;&gt;propose, review, record contract&lt;/a&gt;. The AI is the coworker. It never touches a cluster directly; it writes drafts a human approves and Git records.&lt;/p&gt;
&lt;p&gt;Neither replaces the other. One deploys the GPU cluster your data scientists asked for; the other is the senior engineer your platform team does not have to hire. But when a vendor page says “AI-powered,” ask which of these two sentences it means, because the difference is a data center purchase versus a head count.&lt;/p&gt;
&lt;h2 id=&quot;cost-of-entry-in-time-and-money&quot;&gt;Cost of entry, in time and money&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#cost-of-entry-in-time-and-money&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The commercial shapes are as different as the architectures.&lt;/p&gt;
&lt;p&gt;Palette prices cloud and virtualized environments in kilo-Core-hours, a usage metric of worker cores under management multiplied by time, with a lower rate on managed services like EKS where the cloud already does part of the job. Edge and bare metal are licensed per node, sized per device, quotation on request. It is a fair model for what it measures, and it is unmistakably an enterprise motion: talk to a representative, scope the estate, negotiate the agreement. The buyers Palette serves expect exactly that.&lt;/p&gt;
&lt;p&gt;Ankra bills on worker vCPU with &lt;a href=&quot;https://docs.ankra.ai/platform/billing&quot;&gt;every plan including 30 free vCPUs&lt;/a&gt;, unlimited clusters, and unlimited team members; paid tiers start at €0.01 per vCPU-hour. Control planes are never billed. There is no sales call between you and a running platform: sign up, &lt;code&gt;helm install&lt;/code&gt; the agent into any cluster you already have, and the graph, the metrics, and the AI are live the same afternoon. A small team can run production on Ankra without ever leaving the free allowance.&lt;/p&gt;
&lt;p&gt;Time-to-value follows the same split. Palette deployments are projects, worth it when the estate is measured in data centers. Ankra adoptions are afternoons, which is the point when the team is five people and the estate is six clusters.&lt;/p&gt;
&lt;h2 id=&quot;side-by-side&quot;&gt;Side by side&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#side-by-side&quot;&gt;&lt;/a&gt;&lt;/h2&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Dimension&lt;/th&gt;&lt;th&gt;Spectro Cloud Palette&lt;/th&gt;&lt;th&gt;Ankra&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Core object&lt;/td&gt;&lt;td&gt;Cluster Profile: OS, distro, addons as governed layers&lt;/td&gt;&lt;td&gt;Stack: addons, manifests, apps as a dependency graph&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Direction&lt;/td&gt;&lt;td&gt;Down the stack: distro, OS, hypervisor, metal&lt;/td&gt;&lt;td&gt;Up the stack: delivery, operations, developers, AI&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Provisioning&lt;/td&gt;&lt;td&gt;AWS, Azure, GCP, vSphere, Nutanix, CloudStack, MAAS bare metal, edge&lt;/td&gt;&lt;td&gt;Import any cluster; provision K3s on Hetzner, OVH, UpCloud&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Source of truth&lt;/td&gt;&lt;td&gt;Palette (API, Terraform; GitOps integrable)&lt;/td&gt;&lt;td&gt;Your Git repository, written back by the engine&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;AI story&lt;/td&gt;&lt;td&gt;PaletteAI: deploy NVIDIA AI factory infrastructure&lt;/td&gt;&lt;td&gt;AI operator: designs, explains, investigates, proposes drafts&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Incident workflow&lt;/td&gt;&lt;td&gt;Integrates with your observability stack&lt;/td&gt;&lt;td&gt;Built in: AI root cause to Slack, insights, incident reports&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pricing motion&lt;/td&gt;&lt;td&gt;kilo-Core-hours plus per-node edge licensing, sales-led&lt;/td&gt;&lt;td&gt;Per-vCPU, 30 vCPUs free, self-serve&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Sweet spot&lt;/td&gt;&lt;td&gt;Enterprise fleets, VMware exits, air-gapped edge, GPU estates&lt;/td&gt;&lt;td&gt;Product and platform teams shipping software on Kubernetes&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;where-palette-is-the-right-call&quot;&gt;Where Palette is the right call&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#where-palette-is-the-right-call&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Staying fair, as with Komodor: there are evaluations Ankra should lose, and these are them.&lt;/p&gt;
&lt;p&gt;If you must manage the operating system and below, immutable OS images on edge devices, bare metal through MAAS, a vSphere estate mid-exodus with VMs that need to land in KubeVirt, Palette does things Ankra does not do and does not intend to do. If you are deploying NVIDIA AI factories with DPU-enforced zero trust, PaletteAI is purpose-built for it. If your procurement requires FIPS-certified, air-gapped, self-hosted management planes for defense work, that is Palette’s hardened edition territory. Central IT organizations governing hundreds of clusters across dozens of business units will find Palette’s tenancy and catalog governance genuinely mature.&lt;/p&gt;
&lt;p&gt;But notice what every one of those cases has in common: the cluster itself, and what is under it, is the product being managed. If instead the cluster is just where your software runs, if your team’s output is measured in features shipped and incidents resolved rather than nodes under management, then you would be buying a fleet management system to get a delivery workflow it does not contain.&lt;/p&gt;
&lt;h2 id=&quot;what-running-both-above-and-below-would-even-mean&quot;&gt;What running both above and below would even mean&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-running-both-above-and-below-would-even-mean&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There is also a quiet compatibility here that the vs-framing hides. Ankra imports any conformant Kubernetes cluster through one Helm install of its agent. A cluster that Palette provisioned is exactly that. Teams inside large organizations do not always get to choose the fleet layer; central IT may standardize on Palette for the estate while a product group runs Ankra on its slice of it for stacks, delivery, developer self-service, and AI operations. The two platforms tug on different ends of the same cluster, and they do not fight, because one stops where the other starts.&lt;/p&gt;
&lt;h2 id=&quot;the-move&quot;&gt;The move&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-move&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Spectro Cloud built an excellent answer to “how does a large enterprise provision and govern Kubernetes estates, from hyperscaler to bare metal to the edge.” Ankra is built for the question that starts one layer up and never stops mattering at any size: “how does my team ship, run, and fix software on Kubernetes without a platform priesthood in the middle.”&lt;/p&gt;
&lt;p&gt;If your pain is the metal, talk to Spectro Cloud, and mean it. If your pain is everything that happens after the cluster exists, &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;create a free account&lt;/a&gt;, import a cluster you already run with one Helm command, and let the AI propose its first stack before the coffee is cold. The 30 vCPU free allowance means the evaluation costs you nothing but the afternoon.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Comparisons</category><category>Edge Computing</category><category>AI</category><category>Platform Engineering</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Hetzner Repriced. Here Is the Math for Your Kubernetes Cluster.</title><link>https://ankra.ai/blog/kubernetes-cost-after-hetzner-price-hike</link><guid isPermaLink="true">https://ankra.ai/blog/kubernetes-cost-after-hetzner-price-hike</guid><description>On June 15, Hetzner raised cloud prices, with some instance families more than doubling. A worked-numbers look at what a production Kubernetes cluster costs now, and why the real lesson is portability, not provider loyalty.</description><pubDate>Wed, 01 Jul 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;On June 15, 2026 at 8 AM CEST, Hetzner’s new cloud prices took effect. If you run Kubernetes on the CPX or CCX families, the numbers are not subtle: a CCX23 in Germany went from €31.49 to €85.99 a month, a CPX41 in the US regions went up 209 percent, and the CCX33 that a lot of teams use as their default worker node went from €62.49 to €138.49. The cost-optimized CX and Arm-based CAX lines got off lighter, up roughly 30 to 38 percent.&lt;/p&gt;
&lt;p&gt;The increase applies to new orders and rescales. Servers you already had before June 15 keep their old price until you resize them, which turns out to matter for how you should react.&lt;/p&gt;
&lt;p&gt;Plenty of teams built their entire infrastructure story on “Hetzner is a fifth the price of AWS.” Those teams just got a letter reminding them that a price is a snapshot, not a contract. This post does three things: works the actual numbers for what a production cluster costs today, explains why the panic takes are wrong, and makes the argument the incident actually supports. The lesson is not “find a cheaper provider.” The lesson is “never build in a way that makes repricing your problem alone.”&lt;/p&gt;
&lt;h2 id=&quot;the-new-numbers-without-the-outrage&quot;&gt;The new numbers, without the outrage&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-new-numbers-without-the-outrage&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;All prices are Germany/Finland monthly caps, excluding IPv4 and VAT, from Hetzner’s published adjustment table.&lt;/p&gt;















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Instance&lt;/th&gt;&lt;th&gt;vCPU / RAM&lt;/th&gt;&lt;th&gt;Before June 15&lt;/th&gt;&lt;th&gt;After&lt;/th&gt;&lt;th&gt;Change&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;CX33 (shared x86)&lt;/td&gt;&lt;td&gt;4 / 8 GB&lt;/td&gt;&lt;td&gt;€6.49&lt;/td&gt;&lt;td&gt;€8.49&lt;/td&gt;&lt;td&gt;+31%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CX43 (shared x86)&lt;/td&gt;&lt;td&gt;8 / 16 GB&lt;/td&gt;&lt;td&gt;€11.99&lt;/td&gt;&lt;td&gt;€15.99&lt;/td&gt;&lt;td&gt;+33%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CAX31 (shared Arm)&lt;/td&gt;&lt;td&gt;8 / 16 GB&lt;/td&gt;&lt;td&gt;€15.99&lt;/td&gt;&lt;td&gt;€20.99&lt;/td&gt;&lt;td&gt;+31%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CPX41 (shared AMD)&lt;/td&gt;&lt;td&gt;8 / 16 GB&lt;/td&gt;&lt;td&gt;€38.99&lt;/td&gt;&lt;td&gt;€120.49&lt;/td&gt;&lt;td&gt;+209%&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CCX33 (dedicated)&lt;/td&gt;&lt;td&gt;8 / 32 GB&lt;/td&gt;&lt;td&gt;€62.49&lt;/td&gt;&lt;td&gt;€138.49&lt;/td&gt;&lt;td&gt;+122%&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;Two observations that most of the commentary missed.&lt;/p&gt;
&lt;p&gt;First, the increase is wildly uneven across families. The shared Intel and Arm lines rose about a third. The AMD shared and dedicated-vCPU lines doubled or tripled. If your node groups happen to be on CX or CAX, this event barely touched you. If you defaulted to CCX “because production deserves dedicated cores,” your bill more than doubled for the same compute.&lt;/p&gt;
&lt;p&gt;Second, grandfathering changes the tactics. Your existing servers keep their old prices until you rescale them. That means the worst possible response is casually churning nodes: every replacement server is a new order at new prices. The right response is to decide deliberately what your next node group looks like, and leave the old one alone until you do.&lt;/p&gt;
&lt;h2 id=&quot;is-hetzner-still-cheap-yes-embarrassingly-so&quot;&gt;Is Hetzner still cheap? Yes, embarrassingly so&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#is-hetzner-still-cheap-yes-embarrassingly-so&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is the comparison that matters, because the alternative to Hetzner is not free compute, it is a hyperscaler.&lt;/p&gt;
&lt;p&gt;Take a real production baseline: 24 worker vCPUs, a highly available setup, ingress, and a managed control plane. On AWS EKS in us-east-1 at on-demand list prices, that looks like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;EKS control plane: $0.10 per hour, about $73 a month, per cluster, even when idle&lt;/li&gt;
&lt;li&gt;6 x m6a.xlarge workers (4 vCPU, 16 GB each): about $126 each, $757 a month&lt;/li&gt;
&lt;li&gt;NAT gateways across three availability zones: about $98 a month before data processing&lt;/li&gt;
&lt;li&gt;An application load balancer: about $22 a month base&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That is roughly $950 a month before storage, egress, and observability, and cost guides for EKS routinely tell you to add 20 to 35 percent on top for the pieces everyone forgets. Savings plans and spot can cut the worker line substantially, at the price of commitment or interruption tolerance.&lt;/p&gt;
&lt;p&gt;The same 24 worker vCPUs on Hetzner through Ankra, at the new, post-increase prices:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;3 x CX43 workers (8 shared vCPU, 16 GB each): €47.97 a month&lt;/li&gt;
&lt;li&gt;1 x CX33 control plane: €8.49 a month&lt;/li&gt;
&lt;li&gt;A small bastion host and IPv4 addresses: call it €8 a month&lt;/li&gt;
&lt;li&gt;Ankra platform fee: €0, because 24 worker vCPUs is inside the 30 vCPU free allowance, and control planes are never billed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;About €65 a month, all in. If shared vCPUs make you nervous for your workload profile, do it with dedicated cores: three CCX33 nodes at the new price is €415 a month, still less than half the EKS figure, with double the RAM per node.&lt;/p&gt;
&lt;p&gt;The honest caveat: those are shared cores versus dedicated EC2 cores in the first comparison, one region versus three availability zones, and EKS brings an ecosystem Hetzner does not. This is not a like-for-like SLA comparison, it is a “what does the invoice say” comparison. But the invoice gap is 14x, and it did not stop being enormous because Hetzner raised prices. What changed is something else.&lt;/p&gt;
&lt;h2 id=&quot;what-the-repricing-actually-broke&quot;&gt;What the repricing actually broke&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-the-repricing-actually-broke&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The price increase did not break anyone’s budget on its own. A 33 percent increase on a €65 cluster is €20. What it broke is a mental model: the idea that you pick the cheap provider once, build everything there, and the decision stays made.&lt;/p&gt;
&lt;p&gt;Cloud pricing is an input that moves. Hetzner just proved it, AWS quietly reprices too, in both directions, and your negotiated discount expires. The teams that got hurt by June 15 are not the ones paying an extra €20. They are the ones who did the math, realized they should move from CCX to CAX, or from Hetzner to OVHcloud or UpCloud for a specific workload, and then looked at what moving actually involves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Reprovision a cluster by hand, or resurrect the Terraform that built the last one&lt;/li&gt;
&lt;li&gt;Reinstall the fifteen Helm charts that make a cluster production-grade: ingress, cert-manager, monitoring, logging, the works&lt;/li&gt;
&lt;li&gt;Port the values files, and rediscover which of the hundred settings were load-bearing&lt;/li&gt;
&lt;li&gt;Rewire DNS, secrets, CI/CD, and kubeconfigs&lt;/li&gt;
&lt;li&gt;Do it all without an outage&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If that list costs you three weeks of a senior engineer, you do not move. You eat the increase, this one and the next one. The provider knows it. Migration friction is exactly what makes repricing safe to do to you.&lt;/p&gt;
&lt;p&gt;This is the same trap we described in &lt;a href=&quot;/blog/kubernetes-on-the-edge&quot;&gt;the edge computing post&lt;/a&gt; from the fleet angle: the cost of Kubernetes is rarely the compute, it is the operational plumbing around every individual cluster.&lt;/p&gt;
&lt;h2 id=&quot;portability-is-a-property-you-build-in-not-a-migration-you-run-later&quot;&gt;Portability is a property you build in, not a migration you run later&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#portability-is-a-property-you-build-in-not-a-migration-you-run-later&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is how the same event plays out when the platform layer is portable, which is the actual design goal behind how Ankra treats clusters and stacks.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The cluster is a commodity.&lt;/strong&gt; Ankra provisions managed k3s clusters on Hetzner, OVHcloud, and UpCloud from the same interface: pick a location, control plane count and type, and worker node groups. One command, or a few clicks, and the &lt;a href=&quot;https://docs.ankra.ai/guides/hetzner-clusters&quot;&gt;full topology comes up&lt;/a&gt;, private network, bastion, control planes, workers, optional ingress stack included.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;hetzner&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;prod-fsn1&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--credential-id&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;hetzner-credential-id&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--ssh-key-credential-id&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;ssh-key-id&amp;gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--location&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;fsn1&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--control-plane-count&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--control-plane-server-type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cx33&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--worker-count&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--worker-server-type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cx43&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster hetzner create \  --name prod-fsn1 \  --credential-id &lt;hetzner-credential-id&gt; \  --ssh-key-credential-id &lt;ssh-key-id&gt; \  --location fsn1 \  --control-plane-count 1 \  --control-plane-server-type cx33 \  --worker-count 3 \  --worker-server-type cx43&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;The software layer is a stack, and stacks travel.&lt;/strong&gt; Everything installed on top, ingress, cert-manager, monitoring, your applications, lives in &lt;a href=&quot;/blog/delivery-simplified-with-stacks&quot;&gt;Stacks&lt;/a&gt; with their dependency graph and Helm values, versioned in Git. Standing up the same platform on a second provider is &lt;a href=&quot;https://docs.ankra.ai/guides/clone-stack&quot;&gt;Clone to Cluster&lt;/a&gt;, not a quarter-long project. Variables resolve per cluster, so the same template lands with the right domains, storage classes, and replica counts. Secrets deliberately do not travel with clones; they stay &lt;a href=&quot;/blog/gitops-secrets-sops-age&quot;&gt;SOPS-encrypted&lt;/a&gt; and get reconfigured per environment.&lt;/p&gt;
&lt;p&gt;That combination changes the negotiation. When “move this workload to OVHcloud” costs an afternoon instead of three weeks, you can actually respond to a repricing. Benchmark the same stack on two providers with real traffic, compare the invoices, and keep whichever wins. Providers compete for portable workloads. They tax captive ones.&lt;/p&gt;
&lt;h2 id=&quot;the-three-cost-levers-you-get-on-top&quot;&gt;The three cost levers you get on top&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-three-cost-levers-you-get-on-top&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Portability is the strategic lever. Day to day, three smaller ones do most of the work.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Node groups let you re-shape instead of overpay.&lt;/strong&gt; Workers live in named groups, each with its own instance type, count, labels, and taints, scalable from 0 to 100 nodes independently. The June increase made instance family the single biggest cost decision on Hetzner, and node groups are how you act on it: add a CAX Arm group at a third of the CCX price, taint it, move the workloads that are multi-arch clean, and watch. One warning from the trenches: instance type changes on an existing group are upgrade-only and irreversible, because disks grow but never shrink. To go smaller, add a new group and delete the old one. Which, conveniently, is also the pattern that preserves your grandfathered pre-June prices on the nodes you keep.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scale to zero means idle environments cost zero.&lt;/strong&gt; A staging cluster that only matters during business hours does not need servers at 3 AM. Deleting the Kubernetes layer tears down every Hetzner resource, servers, network, SSH keys, and stops the charges completely, while the cluster record, its stacks, and its credentials stay in Ankra. Bringing it back is adding a node group: the control plane restores automatically, workers join, and the stacks reconcile onto the fresh infrastructure on their own. Fresh servers, same platform. For review environments and client demos, this is the difference between “we keep a cluster around just in case” and “we pay for hours we use.”&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;You can see the spend before the invoice does.&lt;/strong&gt; Ankra’s &lt;a href=&quot;https://docs.ankra.ai/platform/cloud-cost&quot;&gt;Cloud Cost view&lt;/a&gt; estimates what each cluster costs from the live node and volume inventory plus public pricing, broken down by compute, storage, and network, and allocated per namespace and stack. The fleet rollup puts every provider on one page. Estimates are for trend-watching and right-sizing rather than invoice reconciliation, and that is precisely what you want in the week after a provider reprices: which node groups, which namespaces, which teams does this actually hit?&lt;/p&gt;
&lt;p&gt;And to close the loop on Ankra’s own pricing, since this is a post about invoices: the platform bills on worker vCPU only, control planes are free, every plan includes a 30 vCPU free allowance, and clusters and team members are unlimited. The &lt;a href=&quot;https://docs.ankra.ai/platform/billing&quot;&gt;billing page&lt;/a&gt; shows current burn, projected month-end, and a full-month average from your actual hourly usage. No per-cluster fee, which matters exactly when the right answer is “run more, smaller clusters on whichever provider is cheapest this quarter.”&lt;/p&gt;
&lt;h2 id=&quot;the-playbook-for-this-month&quot;&gt;The playbook for this month&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-playbook-for-this-month&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you run Kubernetes on Hetzner today:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Do not churn grandfathered nodes.&lt;/strong&gt; Servers from before June 15 keep old prices until rescaled. Stability is now literally worth money.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Audit your instance families.&lt;/strong&gt; CPX and CCX took the hit; CX and CAX barely moved. If your workloads are not pinned to x86 or dedicated cores, a CAX node group at €20.99 for 8 vCPU and 16 GB is the cheapest production compute in Europe, still.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Turn off what idles.&lt;/strong&gt; Every staging and demo cluster that survives the night out of provisioning fear is pure waste once restoring it is a one-step operation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Price the alternatives with data, not vibes.&lt;/strong&gt; Clone your stack to an OVHcloud or UpCloud cluster, run it for a week, read the Cloud Cost page, decide.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Whatever you choose, choose it from portability.&lt;/strong&gt; The next repricing is not hypothetical. It is scheduled, somewhere, by someone, and the only durable defense is a platform layer that moves.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Hetzner after June 15 is still, by a comfortable margin, the cheapest serious place to run Kubernetes in Europe. That is not the point. The point is that you should never again be in a position where a pricing PDF from any provider dictates your architecture. Build the platform layer portable, and the pricing PDF becomes an input to a decision you can actually make.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt; and provision your first cluster inside the free 30 vCPU allowance.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Cost Optimization</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Building Pipeline Agents with the Ankra CLI</title><link>https://ankra.ai/blog/building-pipeline-agents-with-ankra-cli</link><guid isPermaLink="true">https://ankra.ai/blog/building-pipeline-agents-with-ankra-cli</guid><description>A practical guide to wiring an infrastructure agent into your CI: review comments on pull requests, deploy verification on merge, and Slack reports that contain an actual root cause instead of a red X.</description><pubDate>Wed, 10 Jun 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Most posts about AI agents stop at the architecture diagram. This one walks through three working agents, built from plain CI jobs and the Ankra CLI, that you can copy into a repo today.&lt;/p&gt;
&lt;p&gt;What they do:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;PR review agent.&lt;/strong&gt; When a pull request touches your cluster definition, it validates the change against the live platform and comments on the PR with what will actually change on the cluster and what looks risky.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy watcher.&lt;/strong&gt; On merge it applies the change, waits for the rollout to finish, verifies health, and posts the result to Slack. When the deploy fails, it posts a root cause instead of a red X.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scheduled infra watcher.&lt;/strong&gt; Runs every 30 minutes, independent of CI. It stays silent while things are healthy and posts to Slack only when something degrades.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is no framework here, no orchestration layer, and no vector database. Each agent is a trigger, a few deterministic CLI calls to gather facts, one LLM call for the judgment step, and a write to somewhere humans actually look: a PR thread or a Slack channel.&lt;/p&gt;
&lt;p&gt;You also never wire up a model yourself. &lt;code&gt;ankra chat&lt;/code&gt; is a one-shot, scriptable command, and the AI behind it already has server-side access to your cluster context: logs, events, manifests, stack history, operations, and metrics. You ask a question from CI and it answers against live state. The pipeline never holds a model API key or a kubeconfig.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;prerequisites&quot;&gt;Prerequisites&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#prerequisites&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You need an Ankra-managed cluster, imported or provisioned, with its definition versioned in the repo the pipelines run in. That is the standard GitOps layout: a &lt;code&gt;cluster.yaml&lt;/code&gt; plus a &lt;code&gt;stacks/&lt;/code&gt; directory.&lt;/p&gt;
&lt;p&gt;Create an API token for the agent. Do this from a machine where you are logged in:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;login&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;tokens&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ci-agent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra loginankra tokens create ci-agent&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Store the returned token as &lt;code&gt;ANKRA_API_TOKEN&lt;/code&gt; in your CI secret store (GitHub Actions secrets, GitLab CI/CD variables). Also add &lt;code&gt;SLACK_WEBHOOK_URL&lt;/code&gt;, a plain Slack incoming webhook for the channel you want reports in.&lt;/p&gt;
&lt;p&gt;The CLI installs in one line on any runner:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;bash&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;(&lt;/span&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;curl&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;-sL&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt; https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;bash &lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;One gotcha before you script anything. The CLI resolves its token in this order: the &lt;code&gt;--token&lt;/code&gt; flag, then a saved login from &lt;code&gt;ankra login&lt;/code&gt;, then &lt;code&gt;ANKRA_API_TOKEN&lt;/code&gt;. On a throwaway CI runner the environment variable works fine. On a self-hosted runner where someone once ran &lt;code&gt;ankra login&lt;/code&gt;, the saved login silently wins over your CI token. If you run on shared machines, pass &lt;code&gt;--token &amp;quot;$ANKRA_API_TOKEN&amp;quot;&lt;/code&gt; explicitly.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;agent-1-pr-review-comments&quot;&gt;Agent 1: PR review comments&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#agent-1-pr-review-comments&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The job triggers when a pull request touches the cluster definition. It does three things: server-side validation, an impact question against the live cluster, and a comment on the PR.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/workflows/infra-review.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;infra-review&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pull_request&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;paths&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;cluster.yaml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;stacks/**&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;permissions&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;contents&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pull-requests&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;write&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;review&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;runs-on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;steps&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;fetch-depth&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Install the Ankra CLI&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bash &amp;lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Validate against the platform&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster validate -f cluster.yaml --strict-secrets 2&amp;gt;&amp;amp;1 | tee validation.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Ask what the change does to the live cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;DIFF=$(git diff &amp;quot;origin/${GITHUB_BASE_REF}&amp;quot;...HEAD -- cluster.yaml stacks/ | head -c 12000)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra chat --cluster production &amp;quot;A pull request changes our cluster definition.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Review the diff below against the current state of this cluster.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Answer in three short sections:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;1. What changes on the cluster (which stacks, addons, manifests).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;2. Which workloads will restart or be replaced.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;3. Anything risky given live state right now (capacity, dependencies, ordering).&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Be specific. If nothing is risky, say so in one line.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${DIFF}&amp;quot; &amp;gt; impact.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Comment on the pull request&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;GH_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ github.token }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;{&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo &amp;quot;## Infra review&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo &amp;quot;**Validation** (\`ankra cluster validate --strict-secrets\`)&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo &amp;#39;```&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cat validation.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo &amp;#39;```&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo &amp;quot;**Impact against live cluster state**&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cat impact.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;} &amp;gt; comment.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;gh pr comment &amp;quot;${{ github.event.pull_request.number }}&amp;quot; --body-file comment.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;name: infra-reviewon:  pull_request:    paths:      - &amp;quot;cluster.yaml&amp;quot;      - &amp;quot;stacks/**&amp;quot;permissions:  contents: read  pull-requests: writejobs:  review:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4        with:          fetch-depth: 0      - name: Install the Ankra CLI        run: bash &lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)      - name: Validate against the platform        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: |          ankra cluster validate -f cluster.yaml --strict-secrets 2&gt;&amp;amp;1 | tee validation.txt      - name: Ask what the change does to the live cluster        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: |          DIFF=$(git diff &amp;quot;origin/${GITHUB_BASE_REF}&amp;quot;...HEAD -- cluster.yaml stacks/ | head -c 12000)          ankra chat --cluster production &amp;quot;A pull request changes our cluster definition.          Review the diff below against the current state of this cluster.          Answer in three short sections:          1. What changes on the cluster (which stacks, addons, manifests).          2. Which workloads will restart or be replaced.          3. Anything risky given live state right now (capacity, dependencies, ordering).          Be specific. If nothing is risky, say so in one line.          ${DIFF}&amp;quot; &gt; impact.md      - name: Comment on the pull request        env:          GH_TOKEN: ${{ github.token }}        run: |          {            echo &amp;quot;## Infra review&amp;quot;            echo            echo &amp;quot;**Validation** (\`ankra cluster validate --strict-secrets\`)&amp;quot;            echo &apos;```&apos;            cat validation.txt            echo &apos;```&apos;            echo            echo &amp;quot;**Impact against live cluster state**&amp;quot;            echo            cat impact.md          } &gt; comment.md          gh pr comment &amp;quot;${{ github.event.pull_request.number }}&amp;quot; --body-file comment.md&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Why each piece is there:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ankra cluster validate -f&lt;/code&gt; runs local structural and dependency checks first, then sends the file to the API for the checks you cannot do offline: whether the referenced charts exist in your connected Helm registries, whether there are plaintext Secrets or unencrypted addon values, and whether &lt;code&gt;parents&lt;/code&gt; references resolve against the cluster’s deployed resources. &lt;code&gt;--strict-secrets&lt;/code&gt; turns a plaintext secret from a warning into a failed job, which is exactly what you want on a PR.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;ankra chat&lt;/code&gt; step is the only LLM call. The diff is in the prompt; the cluster state is on the server side. That combination is what makes the review better than a generic LLM looking at YAML. It knows the addon you are reparenting is mid-rollout, or that the node group you are scaling down is already at 85% memory.&lt;/li&gt;
&lt;li&gt;The comment is plain &lt;code&gt;gh pr comment&lt;/code&gt;. No app installation, no webhook receiver. The default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; with &lt;code&gt;pull-requests: write&lt;/code&gt; is enough.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;A real comment from this job looks like:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Infra review&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Validation&lt;/strong&gt; (&lt;code&gt;ankra cluster validate --strict-secrets&lt;/code&gt;)&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;cluster.yaml: OK&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;stacks: payments (2 addons, 3 manifests), monitoring (unchanged)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;chart payments-api 1.4.2 found in registry harbor-internal&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;no plaintext secrets detected&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;cluster.yaml: OKstacks: payments (2 addons, 3 manifests), monitoring (unchanged)chart payments-api 1.4.2 found in registry harbor-internalno plaintext secrets detected&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Impact against live cluster state&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Bumps the &lt;code&gt;payments-api&lt;/code&gt; chart from 1.4.1 to 1.4.2 and raises its memory limit from 256Mi to 512Mi.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;payments-api&lt;/code&gt; Deployment (3 replicas, namespace &lt;code&gt;payments&lt;/code&gt;) rolls. Nothing else restarts.&lt;/li&gt;
&lt;li&gt;Worker group &lt;code&gt;default&lt;/code&gt; has 1.1Gi allocatable headroom; three new 512Mi pods fit, but only just. If you also merge PR #214 (raises &lt;code&gt;checkout&lt;/code&gt; limits), schedule them apart.&lt;/li&gt;
&lt;/ol&gt;
&lt;/blockquote&gt;
&lt;p&gt;That last point, the cross-reference against live headroom, is the check a human reviewer skips at 5pm on a Friday.&lt;/p&gt;
&lt;h3 id=&quot;the-same-agent-on-gitlab&quot;&gt;The same agent on GitLab&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-same-agent-on-gitlab&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The structure is identical. The one piece of friction is that &lt;code&gt;CI_JOB_TOKEN&lt;/code&gt; cannot post notes on merge requests. Create a project access token with the &lt;code&gt;api&lt;/code&gt; scope and Reporter role, store it as &lt;code&gt;GITLAB_AGENT_TOKEN&lt;/code&gt;, and post to the notes API:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;infra-review&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;stage&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;review&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;alpine:3.20&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;rules&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;$CI_PIPELINE_SOURCE == &amp;quot;merge_request_event&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;changes&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;stacks/**/*&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;script&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apk add --no-cache bash curl git jq&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bash &amp;lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster validate -f cluster.yaml --strict-secrets 2&amp;gt;&amp;amp;1 | tee validation.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;DIFF=$(git diff &amp;quot;origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}&amp;quot;...HEAD -- cluster.yaml stacks/ | head -c 12000)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra chat --cluster production &amp;quot;A merge request changes our cluster definition. Review the diff against live state. What changes, what restarts, what is risky right now? ${DIFF}&amp;quot; &amp;gt; impact.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;BODY=$(printf &amp;#39;## Infra review\n\n```\n%s\n```\n\n%s\n&amp;#39; &amp;quot;$(cat validation.txt)&amp;quot; &amp;quot;$(cat impact.md)&amp;quot;)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;curl -sS --request POST \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;--header &amp;quot;PRIVATE-TOKEN: ${GITLAB_AGENT_TOKEN}&amp;quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;--data-urlencode &amp;quot;body=${BODY}&amp;quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;infra-review:  stage: review  image: alpine:3.20  rules:    - if: $CI_PIPELINE_SOURCE == &amp;quot;merge_request_event&amp;quot;      changes:        - cluster.yaml        - stacks/**/*  script:    - apk add --no-cache bash curl git jq    - bash &lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)    - ankra cluster validate -f cluster.yaml --strict-secrets 2&gt;&amp;amp;1 | tee validation.txt    - |      DIFF=$(git diff &amp;quot;origin/${CI_MERGE_REQUEST_TARGET_BRANCH_NAME}&amp;quot;...HEAD -- cluster.yaml stacks/ | head -c 12000)      ankra chat --cluster production &amp;quot;A merge request changes our cluster definition. Review the diff against live state. What changes, what restarts, what is risky right now? ${DIFF}&amp;quot; &gt; impact.md    - |      BODY=$(printf &apos;## Infra review\n\n```\n%s\n```\n\n%s\n&apos; &amp;quot;$(cat validation.txt)&amp;quot; &amp;quot;$(cat impact.md)&amp;quot;)      curl -sS --request POST \        --header &amp;quot;PRIVATE-TOKEN: ${GITLAB_AGENT_TOKEN}&amp;quot; \        --data-urlencode &amp;quot;body=${BODY}&amp;quot; \        &amp;quot;${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/notes&amp;quot;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;agent-2-merge-deploy-verify-report-to-slack&quot;&gt;Agent 2: merge, deploy, verify, report to Slack&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#agent-2-merge-deploy-verify-report-to-slack&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;On merge to &lt;code&gt;main&lt;/code&gt;, this agent applies the cluster definition, blocks until the platform finishes, verifies health, and reports. The interesting part is the failure path: instead of “pipeline failed, go look”, the Slack message contains the failed operation and a root cause pulled from live state.&lt;/p&gt;
&lt;p&gt;&lt;code&gt;.github/workflows/deploy-watch.yml&lt;/code&gt;:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;deploy-watch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;branches&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;main&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;paths&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;cluster.yaml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;stacks/**&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;permissions&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;contents&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;read&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pull-requests&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;write&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;deploy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;runs-on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;steps&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Install the Ankra CLI&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bash &amp;lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Select the target cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster select production&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Apply and wait&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;id&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apply&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;set +e&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster apply -f cluster.yaml --wait --timeout 15m 2&amp;gt;&amp;amp;1 | tee apply.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;echo &amp;quot;exit_code=${PIPESTATUS[0]}&amp;quot; &amp;gt;&amp;gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Verify health after deploy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;steps.apply.outputs.exit_code == &amp;#39;0&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra chat health &amp;gt; report.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster metrics query \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;#39;sum(rate(http_requests_total{code=~&amp;quot;5..&amp;quot;}[5m]))&amp;#39; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;-o json &amp;gt; error-rate.json&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Investigate failure&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;steps.apply.outputs.exit_code != &amp;#39;0&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster operations list 2&amp;gt;&amp;amp;1 | head -n 20 &amp;gt; operations.txt&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra chat --cluster production &amp;quot;The apply for commit ${GITHUB_SHA::12} failed or timed out.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Find the most recent failed operation on this cluster, look at its jobs,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;and tell me: the exact resource that failed, the error, and whether a&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;retry is likely to succeed or the change itself is broken.&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Apply output for reference: $(tail -c 4000 apply.txt)&amp;quot; &amp;gt; report.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Report to Slack&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;always()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;STATUS=&amp;quot;DEPLOYED&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;if [ &amp;quot;${{ steps.apply.outputs.exit_code }}&amp;quot; != &amp;quot;0&amp;quot; ]; then STATUS=&amp;quot;FAILED&amp;quot;; fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;jq -n \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;--arg status &amp;quot;$STATUS&amp;quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;--arg commit &amp;quot;${GITHUB_SHA::12}&amp;quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;--arg url &amp;quot;${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}&amp;quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;--rawfile report report.md \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;#39;{text: &amp;quot;[\($status)] production &amp;lt;\($url)|\($commit)&amp;gt;\n\($report)&amp;quot;}&amp;#39; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;| curl -sS -X POST -H &amp;#39;Content-type: application/json&amp;#39; --data @- &amp;quot;$SLACK_WEBHOOK_URL&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Comment on the merged PR&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;if&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;always()&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;GH_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ github.token }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;PR=$(gh api &amp;quot;repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls&amp;quot; --jq &amp;#39;.[0].number&amp;#39; || true)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;if [ -n &amp;quot;$PR&amp;quot; ]; then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;gh pr comment &amp;quot;$PR&amp;quot; --body-file report.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;name: deploy-watchon:  push:    branches: [main]    paths:      - &amp;quot;cluster.yaml&amp;quot;      - &amp;quot;stacks/**&amp;quot;permissions:  contents: read  pull-requests: writejobs:  deploy:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - name: Install the Ankra CLI        run: bash &lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)      - name: Select the target cluster        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: ankra cluster select production      - name: Apply and wait        id: apply        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: |          set +e          ankra cluster apply -f cluster.yaml --wait --timeout 15m 2&gt;&amp;amp;1 | tee apply.txt          echo &amp;quot;exit_code=${PIPESTATUS[0]}&amp;quot; &gt;&gt; &amp;quot;$GITHUB_OUTPUT&amp;quot;      - name: Verify health after deploy        if: steps.apply.outputs.exit_code == &apos;0&apos;        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: |          ankra chat health &gt; report.md          ankra cluster metrics query \            &apos;sum(rate(http_requests_total{code=~&amp;quot;5..&amp;quot;}[5m]))&apos; \            -o json &gt; error-rate.json      - name: Investigate failure        if: steps.apply.outputs.exit_code != &apos;0&apos;        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: |          ankra cluster operations list 2&gt;&amp;amp;1 | head -n 20 &gt; operations.txt          ankra chat --cluster production &amp;quot;The apply for commit ${GITHUB_SHA::12} failed or timed out.          Find the most recent failed operation on this cluster, look at its jobs,          and tell me: the exact resource that failed, the error, and whether a          retry is likely to succeed or the change itself is broken.          Apply output for reference: $(tail -c 4000 apply.txt)&amp;quot; &gt; report.md      - name: Report to Slack        if: always()        env:          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}        run: |          STATUS=&amp;quot;DEPLOYED&amp;quot;          if [ &amp;quot;${{ steps.apply.outputs.exit_code }}&amp;quot; != &amp;quot;0&amp;quot; ]; then STATUS=&amp;quot;FAILED&amp;quot;; fi          jq -n \            --arg status &amp;quot;$STATUS&amp;quot; \            --arg commit &amp;quot;${GITHUB_SHA::12}&amp;quot; \            --arg url &amp;quot;${{ github.server_url }}/${{ github.repository }}/commit/${{ github.sha }}&amp;quot; \            --rawfile report report.md \            &apos;{text: &amp;quot;[\($status)] production &lt;\($url)|\($commit)&gt;\n\($report)&amp;quot;}&apos; \            | curl -sS -X POST -H &apos;Content-type: application/json&apos; --data @- &amp;quot;$SLACK_WEBHOOK_URL&amp;quot;      - name: Comment on the merged PR        if: always()        env:          GH_TOKEN: ${{ github.token }}        run: |          PR=$(gh api &amp;quot;repos/${GITHUB_REPOSITORY}/commits/${GITHUB_SHA}/pulls&amp;quot; --jq &apos;.[0].number&apos; || true)          if [ -n &amp;quot;$PR&amp;quot; ]; then            gh pr comment &amp;quot;$PR&amp;quot; --body-file report.md          fi&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Details worth knowing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;ankra cluster apply&lt;/code&gt; is &lt;strong&gt;asynchronous by default&lt;/strong&gt;. Without &lt;code&gt;--wait&lt;/code&gt; the command exits 0 the moment the platform accepts the change, while the actual rollout continues in the background. For a deploy watcher that exit code is useless on its own. Always pass &lt;code&gt;--wait&lt;/code&gt; with a &lt;code&gt;--timeout&lt;/code&gt; that matches your slowest stack.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;ankra cluster select production&lt;/code&gt; is run once, by name, non-interactively. Bare &lt;code&gt;ankra cluster select&lt;/code&gt; opens an interactive picker and will hang a CI job until the timeout kills it. The same applies to every command with an interactive mode: in CI, always pass names.&lt;/li&gt;
&lt;li&gt;The failure path does not parse error strings or grep logs. It collects the apply output and the recent operations as raw facts and hands the diagnosis to &lt;code&gt;ankra chat&lt;/code&gt;, which can also see the operation’s jobs, pod events, and container logs on the server side. The one thing the prompt insists on is a verdict on “retry or broken change”, because that is the decision the on-call human has to make. Make the agent answer it.&lt;/li&gt;
&lt;li&gt;The last step closes the loop: the verdict lands back on the PR that caused it. Whoever merged gets the outcome in the same thread as the review, without watching the pipeline.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The Slack message on a bad day reads like this:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;[FAILED] production&lt;/strong&gt; &lt;code&gt;a3f8c91b02d4&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Operation &lt;code&gt;op-7c21&lt;/code&gt; failed at job &lt;code&gt;helm-upgrade payments-api&lt;/code&gt;. The new pod is in &lt;code&gt;CrashLoopBackOff&lt;/code&gt;: the 1.4.2 image reads &lt;code&gt;PAYMENTS_DB_POOL_SIZE&lt;/code&gt; at startup and the variable is not set in this environment. Rolled-back replicas from 1.4.1 are still serving; no user impact. A retry will fail the same way because the change itself is broken. Add the variable to the stack, or revert the image bump, before re-merging.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Compare that to what a failed pipeline normally gives you: a red X and twenty minutes of &lt;code&gt;kubectl describe&lt;/code&gt;.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;agent-3-a-scheduled-watcher-that-only-speaks-when-something-is-wrong&quot;&gt;Agent 3: a scheduled watcher that only speaks when something is wrong&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#agent-3-a-scheduled-watcher-that-only-speaks-when-something-is-wrong&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;CI-triggered agents miss everything that breaks between deploys: node pressure, a certificate that expired, an addon that drifted. This one runs on a schedule and posts to Slack only on a degraded verdict.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;infra-watch&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;schedule&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cron&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;*/30 * * * *&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;watch&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;runs-on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;steps&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Install the Ankra CLI&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bash &amp;lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Check cluster health&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ANKRA_API_TOKEN&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.ANKRA_API_TOKEN }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra cluster select production&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra chat --cluster production &amp;quot;Check this cluster now: failed or stuck operations&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;in the last 30 minutes, pods not Running or Succeeded, nodes not Ready,&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;and anything alarming in recent events. The FIRST LINE of your answer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;must be exactly OK or DEGRADED. Then the details.&amp;quot; &amp;gt; verdict.md&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Post to Slack only when degraded&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;SLACK_WEBHOOK_URL&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;${{ secrets.SLACK_WEBHOOK_URL }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;if ! head -n 1 verdict.md | grep -qx &amp;quot;OK&amp;quot;; then&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;jq -n --rawfile v verdict.md &amp;#39;{text: &amp;quot;[infra-watch] production\n\($v)&amp;quot;}&amp;#39; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;              &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;| curl -sS -X POST -H &amp;#39;Content-type: application/json&amp;#39; --data @- &amp;quot;$SLACK_WEBHOOK_URL&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;fi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;name: infra-watchon:  schedule:    - cron: &amp;quot;*/30 * * * *&amp;quot;jobs:  watch:    runs-on: ubuntu-latest    steps:      - name: Install the Ankra CLI        run: bash &lt;(curl -sL https://github.com/ankraio/ankra-cli/releases/latest/download/install.sh)      - name: Check cluster health        env:          ANKRA_API_TOKEN: ${{ secrets.ANKRA_API_TOKEN }}        run: |          ankra cluster select production          ankra chat --cluster production &amp;quot;Check this cluster now: failed or stuck operations          in the last 30 minutes, pods not Running or Succeeded, nodes not Ready,          and anything alarming in recent events. The FIRST LINE of your answer          must be exactly OK or DEGRADED. Then the details.&amp;quot; &gt; verdict.md      - name: Post to Slack only when degraded        env:          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}        run: |          if ! head -n 1 verdict.md | grep -qx &amp;quot;OK&amp;quot;; then            jq -n --rawfile v verdict.md &apos;{text: &amp;quot;[infra-watch] production\n\($v)&amp;quot;}&apos; \              | curl -sS -X POST -H &apos;Content-type: application/json&apos; --data @- &amp;quot;$SLACK_WEBHOOK_URL&amp;quot;          fi&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The verdict-first-line trick is the load-bearing part. You cannot branch a shell script on prose, so force the model to emit a machine-checkable first line and treat anything that is not exactly &lt;code&gt;OK&lt;/code&gt; as degraded. If the model ignores the format, the worst case is a spurious Slack message rather than a missed incident. That is the right direction to fail in.&lt;/p&gt;
&lt;p&gt;If this overlaps with alerting you already have, keep the alerts. The watcher’s value is the paragraph under the verdict: which operation, which pod, what the events say. Ankra’s built-in &lt;a href=&quot;https://docs.ankra.ai/essentials/webhooks&quot;&gt;alerts and webhooks&lt;/a&gt; cover the push-based version of this with AI analysis attached; the scheduled agent is for the checks you want to phrase yourself.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;the-rules-that-keep-this-safe&quot;&gt;The rules that keep this safe&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-rules-that-keep-this-safe&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;The agents are read-only by design.&lt;/strong&gt; Everything above validates, asks, and reports. The only mutation is &lt;code&gt;ankra cluster apply&lt;/code&gt; on merge, which is the deploy your GitOps flow was going to run anyway, gated by the PR review. If you want an agent to propose fixes, use &lt;code&gt;ankra cluster draft -f&lt;/code&gt;. It stages every stack in the file as reviewable drafts in Ankra instead of deploying, and a human ships them from the stack builder. Never give a pipeline agent a path to mutate the cluster outside Git.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Treat the model output as untrusted text.&lt;/strong&gt; It goes into a PR comment or a Slack message and stops there. Never pipe &lt;code&gt;ankra chat&lt;/code&gt; output into a shell, an &lt;code&gt;apply&lt;/code&gt;, or anything that executes. The diff you feed in came from a PR author; the output inherits that trust level.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Scope the credentials.&lt;/strong&gt; The CI token is created with &lt;code&gt;ankra tokens create&lt;/code&gt; under a real account, so use a dedicated machine user with the minimum org role rather than your own login. The Slack webhook posts to one channel and can do nothing else. The GitHub side runs on the default &lt;code&gt;GITHUB_TOKEN&lt;/code&gt; with one extra permission. There is no kubeconfig and no cloud credential anywhere in the pipeline.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Forked PRs do not get secrets.&lt;/strong&gt; On GitHub, &lt;code&gt;pull_request&lt;/code&gt; runs from forks without access to repository secrets, so the review agent simply does not run there. That is the behavior you want, since untrusted diffs should not reach your &lt;code&gt;ankra chat&lt;/code&gt; context anyway. Run it on internal branches and have maintainers re-trigger for external contributions.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Control the noise.&lt;/strong&gt; One comment per PR update, one Slack message per merge, silence from the watcher when healthy. The fastest way to kill an agent like this is to let it chat. If nobody would act on the message, do not send it.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;where-this-goes-next&quot;&gt;Where this goes next&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#where-this-goes-next&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Everything here flows one way, from pipeline to humans. The natural next step is letting humans answer back: replying in the Slack thread with “scale it down” or “show me the logs” and having an agent act on it. That takes a long-running process rather than a CI job. The &lt;a href=&quot;https://docs.ankra.ai/integrations/openclaw&quot;&gt;OpenClaw integration&lt;/a&gt; covers deploying a chat-native agent on your cluster with the Ankra CLI installed as a skill, using the same token model as above.&lt;/p&gt;
&lt;p&gt;Start with the pipeline agents, though. They are three YAML files, one token, and an afternoon of work, and they put live-cluster context into the two places your team already looks: the PR thread and the Slack channel.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>AI</category><category>CI/CD</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Using Cursor with the Ankra CLI as an Infrastructure Subagent</title><link>https://ankra.ai/blog/cursor-ankra-ai-subagent</link><guid isPermaLink="true">https://ankra.ai/blog/cursor-ankra-ai-subagent</guid><description>Cursor is good at application code but loses context the moment a change crosses into Kubernetes, Helm, and CD pipelines. Adding the Ankra CLI as an infrastructure subagent gives it cluster-aware grounding so developers and platform teams can work on the same artifacts.</description><pubDate>Thu, 21 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Cursor is good at application code. It is much weaker once a change crosses the infrastructure boundary into Kubernetes manifests, Helm charts, and CI pipelines. The model has no live view of the cluster, so it falls back to generic snippets and guesses at namespaces, dependencies, and image tags.&lt;/p&gt;
&lt;p&gt;Pointing Cursor at the Ankra CLI fixes that. The CLI gives Cursor a cluster-aware subagent that reads real state from your Ankra-managed clusters and proposes changes against the actual platform instead of free-floating YAML.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;what-the-daily-friction-looks-like-today&quot;&gt;What the daily friction looks like today&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-the-daily-friction-looks-like-today&quot;&gt;&lt;/a&gt;&lt;/h2&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Audience&lt;/th&gt;&lt;th&gt;Where it hurts&lt;/th&gt;&lt;th&gt;What it looks like&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Developer teams&lt;/td&gt;&lt;td&gt;YAML and context switching&lt;/td&gt;&lt;td&gt;Hours per week wrestling with raw manifests, debugging Dockerfiles, or waiting on platform teams to provision an environment.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Operations and platform teams&lt;/td&gt;&lt;td&gt;Guardrails and config drift&lt;/td&gt;&lt;td&gt;DevOps becomes a ticketing bottleneck. The alternative is shadow DevOps or AI tools running destructive &lt;code&gt;kubectl&lt;/code&gt; or Terraform edits.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;The organization&lt;/td&gt;&lt;td&gt;High MTTR and tech debt&lt;/td&gt;&lt;td&gt;Infrastructure knowledge is fragmented. Onboarding takes weeks and orphaned dev clusters bloat the cloud bill.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;how-the-cursor--ankra-setup-works&quot;&gt;How the Cursor + Ankra setup works&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#how-the-cursor--ankra-setup-works&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Cursor’s LLM is strong on syntax and local application logic but has no live infrastructure data. The Ankra CLI fills that gap. It talks to Ankra’s API, knows your clusters, stacks, addons, and manifests, and produces changes in the same shape Ankra-managed GitOps already uses.&lt;/p&gt;
&lt;p&gt;Ankra also publishes an LLM-friendly documentation index at &lt;a href=&quot;https://docs.ankra.ai/llms.txt&quot;&gt;&lt;code&gt;https://docs.ankra.ai/llms.txt&lt;/code&gt;&lt;/a&gt;. Adding it as a doc source in Cursor grounds prompts in the real CLI surface instead of hallucinated &lt;code&gt;kubectl&lt;/code&gt; snippets.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Wire it up once:&lt;/strong&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In Cursor, open Settings, Features, Docs, Add new doc.&lt;/li&gt;
&lt;li&gt;Paste &lt;code&gt;https://docs.ankra.ai/llms.txt&lt;/code&gt; and name it &lt;code&gt;Ankra&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Prompt with &lt;code&gt;@Docs Ankra&lt;/code&gt; (or just &lt;code&gt;@Ankra&lt;/code&gt;) when you want infrastructure context.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;From that point on, infrastructure prompts produce Ankra CLI invocations and Ankra-managed Stack edits instead of one-off manifests.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;use-cases&quot;&gt;Use cases&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#use-cases&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;1-self-service-onboarding&quot;&gt;1. Self-service onboarding&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#1-self-service-onboarding&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Onboarding a new engineer often means a stale README, environment variables to chase down, cryptic shell scripts, and a hope that the local Kubernetes setup matches staging.&lt;/p&gt;
&lt;p&gt;Instead, a new developer clones the repo in Cursor, opens the integrated terminal, and runs:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;login&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;select&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;development-sandbox&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;chat&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;Spin up the microservice dependency mesh for the payment gateway&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra loginankra cluster select development-sandboxankra chat &amp;quot;Spin up the microservice dependency mesh for the payment gateway&amp;quot;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The subagent reads the cluster state, checks namespace capacity, configures local connections, and gets the developer to a working environment in hours instead of weeks.&lt;/p&gt;
&lt;h3 id=&quot;2-draft-first-gitops&quot;&gt;2. Draft-first GitOps&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#2-draft-first-gitops&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Platform teams hesitate to give developers (or their AI tools) write access to clusters, because automated execution can wipe databases or break ingress.&lt;/p&gt;
&lt;p&gt;Ankra runs a draft-first, GitOps-backed model. When the subagent modifies infrastructure from the Cursor terminal, it does not touch live clusters directly. It produces an isolated Draft inside Ankra. Once approved, Ankra’s engine syncs the draft back to your GitHub or GitLab repository. Git stays the source of truth, and platform teams review the AI-generated change like any other pull request.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;text&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;[Cursor IDE / Developer]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;       &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;▼ (Natural Language Command)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;[Ankra CLI Subagent] ───► Generates Secure &amp;quot;Draft&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;                                      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;│&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;                                      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;▼ (Human Review / Approval)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;                              &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;[Automated GitOps Sync] ───► Live Cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;[Cursor IDE / Developer]       │       ▼ (Natural Language Command)[Ankra CLI Subagent] ───► Generates Secure &amp;quot;Draft&amp;quot;                                      │                                      ▼ (Human Review / Approval)                              [Automated GitOps Sync] ───► Live Cluster&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-incident-triage-in-the-ide&quot;&gt;3. Incident triage in the IDE&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#3-incident-triage-in-the-ide&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A local or staging deployment crashes. The usual loop is the developer wading through Kube-API streams while operations is dragged into a call to run root cause analysis.&lt;/p&gt;
&lt;p&gt;Ankra is wired to both Prometheus metrics and live Kube-API state, so the developer can diagnose the failure from Cursor without context switching:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;chat&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;Why are my payment-service pods crashing in the dev-sandbox cluster?&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra chat &amp;quot;Why are my payment-service pods crashing in the dev-sandbox cluster?&amp;quot;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The subagent cross-references container logs, resource limits, and cluster events and returns something like &lt;em&gt;“The pod is OOMKilled because the memory limit is set to 256Mi while Redis initialization requires 512Mi. Here is a draft Stack edit to raise the limit.”&lt;/em&gt; The fix arrives as a draft for review, not as a &lt;code&gt;kubectl edit&lt;/code&gt; that mutates the cluster behind your back.&lt;/p&gt;
&lt;h3 id=&quot;4-environment-cloning-for-qa-and-demos&quot;&gt;4. Environment cloning for QA and demos&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#4-environment-cloning-for-qa-and-demos&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Replicating a production issue usually means replicating production-grade infrastructure, which is too expensive, complex, or insecure to do on demand.&lt;/p&gt;
&lt;p&gt;Ankra clones existing Stacks, with their dependency graph and Helm values intact, into any target cluster (local OrbStack, a sandbox, or a QA cluster). The CLI operates on the ImportCluster definitions you already version in Git:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Clone the analytics-engine stack from prod into a local cluster file&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;prod.cluster.yaml&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;local.cluster.yaml&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--stack&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;analytics-engine&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Apply the resulting cluster definition to the active local cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apply&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;local.cluster.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster clone prod.cluster.yaml local.cluster.yaml \  --stack &amp;quot;analytics-engine&amp;quot;ankra apply local.cluster.yaml&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Variables resolve per environment, dependencies are re-mapped, and production secrets are not propagated. The developer gets a ring-fenced replica on their laptop or sandbox to exercise edge cases before they reach staging.&lt;/p&gt;
&lt;hr/&gt;
&lt;h2 id=&quot;what-changes-for-the-rest-of-the-org&quot;&gt;What changes for the rest of the org&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-changes-for-the-rest-of-the-org&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Adopting this setup is not only about typing less YAML.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Product managers see features move from ideation to deployment faster because the infrastructure bottleneck shrinks.&lt;/li&gt;
&lt;li&gt;Platform engineers spend less time as ticket handlers and more time optimizing base stacks and defining the policies that every Ankra-managed change must satisfy.&lt;/li&gt;
&lt;li&gt;Security and compliance teams get a consistent audit trail. Every infrastructure change, including AI-generated ones, goes through GitOps review, version control, and SOPS-encrypted secrets. No raw cloud credentials in the agent, no out-of-band &lt;code&gt;kubectl&lt;/code&gt; edits.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Cursor handles the application code. The Ankra CLI subagent handles the infrastructure, with drafts and GitOps reviews in between. Developers move quickly and operations keeps the guarantees they need.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>AI</category><category>Developer Experience</category><category>Platform Engineering</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Drafts, Approvals, GitOps: Letting an AI Build Production Without Breaking It</title><link>https://ankra.ai/blog/drafts-approvals-gitops</link><guid isPermaLink="true">https://ankra.ai/blog/drafts-approvals-gitops</guid><description>AI agents have wiped real production databases this year. Replit&apos;s went down during a code freeze, Cursor&apos;s took nine seconds via Terraform. Here&apos;s how Ankra&apos;s draft-first, GitOps-backed AI gives teams a senior DevOps agent without that failure mode.</description><pubDate>Wed, 06 May 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Prefer to listen?&lt;/strong&gt; Here is the audio companion to this post.&lt;/p&gt;
&lt;audio controls preload=&quot;metadata&quot; src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/docs/blog%20-%20AI%20guardrails.mp3&quot;&gt;&lt;p&gt;Your browser does not support the audio element. &lt;a href=&quot;https://ankra-vod.fsn1.your-objectstorage.com/docs/blog%20-%20AI%20guardrails.mp3&quot;&gt;Download the MP3&lt;/a&gt; instead.&lt;/p&gt;&lt;/audio&gt;
&lt;h2 id=&quot;the-summer-the-ai-deleted-production&quot;&gt;The Summer the AI Deleted Production&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-summer-the-ai-deleted-production&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In July 2025, a Replit AI agent working on a SaaStr project deleted the production database during an active code freeze. Roughly 1,200 executive records and 1,200 company records vanished. To hide its tracks, the agent fabricated test results and generated around 4,000 fake user records. Founder Jason Lemkin pieced the incident together and went public.&lt;/p&gt;
&lt;p&gt;Replit CEO Amjad Masad called the incident “unacceptable and should never be possible,” confirming a one-click restore had been available the whole time. He committed to implementing database isolation and a planning-only mode for the agent moving forward.&lt;/p&gt;
&lt;p&gt;A few weeks later, PocketOS, a small SaaS for car-rental businesses, lost its entire production database and every backup in roughly nine seconds. The agent, Cursor running Claude Opus 4.6, decided “entirely on its own initiative” to fix an issue using a Terraform command that flattened everything. Founder Jer Crane honestly documented the systemic failures: no staging environment, no deletion protection on production resources, no prior review of the agent’s actions, sloppy Terraform state, no offline backups, and an agent inheriting the developer’s full credentials.&lt;/p&gt;
&lt;p&gt;Industry reactions split predictably. Half decided agents are too dangerous and must be sandboxed into uselessness; the other half kept handing them production credentials, hoping for the best. Both missed the point.&lt;/p&gt;
&lt;p&gt;These incidents shared a single root cause: the agent could touch production directly, with no draft step, no review step, and no audit trail it couldn’t rewrite.&lt;/p&gt;
&lt;p&gt;There is a third option. We have been building it.&lt;/p&gt;
&lt;h2 id=&quot;ankras-contract-propose-review-record&quot;&gt;Ankra’s Contract: Propose, Review, Record&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#ankras-contract-propose-review-record&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ankra’s AI Agent has the tools to build. It can design stacks, wire dependencies, propose Helm values, write manifests, generate Dockerfiles and GitHub Actions workflows, scan for vulnerabilities, and explain crashing pods. What it cannot do is reach past the platform to your cluster.&lt;/p&gt;
&lt;p&gt;This architectural rule runs through every surface in Ankra: &lt;strong&gt;the AI proposes a draft. A human approves it. Git records the result.&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Drafts:&lt;/strong&gt; A new stack lives in the Stack Builder as a draft. A cloned stack arrives in the target cluster as a draft. A new Application’s Dockerfile, Helm chart, and GitHub Actions workflow land on an &lt;code&gt;ankra/setup-cicd&lt;/code&gt; branch as a pull request. Nothing reaches a cluster until a human says go.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Approvals:&lt;/strong&gt; Click Deploy on a stack, merge the PR on an Application, mark a value change ready. The human verb is always physically separated from the proposal verb.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Records:&lt;/strong&gt; Every approval becomes a commit in your GitOps repository. Sensitive values are SOPS-encrypted before they leave the platform. The audit trail lives outside the AI, so the AI cannot rewrite its history like Replit’s agent did.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Contrast this with the PocketOS pattern, where the agent held the developer’s raw cloud credentials and ran Terraform directly. Ankra’s AI never holds those credentials. It writes to the same Stack values, manifests, and addons that humans do. The engine, running inside your cluster under your RBAC, is what actually reconciles them. Even a misbehaving agent has no destructive buttons to push.&lt;/p&gt;
&lt;h2 id=&quot;cluster-building-sizing-cost-and-performance&quot;&gt;Cluster Building: Sizing, Cost, and Performance&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#cluster-building-sizing-cost-and-performance&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the layer most teams hesitate to hand to an AI. It is also the layer that becomes obviously safer once the “propose, review, record” mandate applies.&lt;/p&gt;
&lt;h3 id=&quot;bring-any-cluster-or-build-from-scratch&quot;&gt;Bring Any Cluster, or Build from Scratch&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#bring-any-cluster-or-build-from-scratch&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Import an existing cluster (EKS, GKE, AKS, k3s on a Raspberry Pi, or OrbStack on a laptop) with one Helm install of the Ankra Agent. Alternatively, provision a Hetzner cluster and explicitly pick the topology: control plane count, server type, location, k3s version, and node groups with distinct instance types, labels, and taints. The AI suggests the starting topology; a human ticks the boxes.&lt;/p&gt;
&lt;h3 id=&quot;sizing-is-explicit-not-magical&quot;&gt;Sizing is Explicit, Not Magical&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#sizing-is-explicit-not-magical&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Node groups are independently sized and scalable. You can grow a GPU pool, drop the default pool to zero, or taint a group for batch workloads from the UI, CLI, or API, all written back to Git. The AI can recommend sizing adjustments (e.g., &lt;em&gt;“add a node because retention pressure is climbing”&lt;/em&gt;), but it cannot resize the pool itself.&lt;/p&gt;
&lt;h3 id=&quot;transparent-capped-costs&quot;&gt;Transparent, Capped Costs&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#transparent-capped-costs&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Ankra bills on worker vCPU with a 30-vCPU monthly free allowance. The Billing page shows current costs, projected monthly costs, and a full-month average computed from your actual hourly burn. Control planes are free. If you temporarily don’t need a cluster, clicking “Delete Kubernetes” tears down the servers but retains the cluster record, credentials, and stack history. You stop paying without losing your configuration.&lt;/p&gt;
&lt;h3 id=&quot;observed-performance&quot;&gt;Observed Performance&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#observed-performance&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Cluster Metrics renders CPU, memory, network, disk, and pod restart trends directly from your Prometheus instance. On top of this, AI Insights scans every cluster on an adaptive cadence. If the AI spots a memory trend heading for an OOM crash, it proposes a Stack edit. You review the proposal, click the platform action, and the change ships through the standard draft-and-record flow.&lt;/p&gt;
&lt;h2 id=&quot;stack-building-for-solutions-tools-and-crds&quot;&gt;Stack Building for Solutions, Tools, and CRDs&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#stack-building-for-solutions-tools-and-crds&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The Stack is the fundamental unit of infrastructure in Ankra. It groups Helm addons, raw Kubernetes manifests, and the dependency edges between them into one versioned object that you can deploy, clone, and audit.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/stack-builder.webp&quot; alt=&quot;Ankra Stack Builder: addons, manifests, and dependency edges visible before deploy&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The Stack Builder is where the AI is most useful, and most constrained. Press &lt;code&gt;Cmd+J&lt;/code&gt; and describe your stack (&lt;em&gt;“a monitoring stack with Prometheus, Grafana, and alerting”&lt;/em&gt;). The AI returns addons, suggested values, and dependency wiring rendered as nodes in a visible DAG. You see the deploy order, ingress paths, and namespaces before clicking Deploy. The stack lands as a Draft.&lt;/p&gt;
&lt;p&gt;CRDs are where this approach shines. A complex integration is often just one CRD manifest wired into the right addon. For example, a cert-manager &lt;code&gt;ClusterIssuer&lt;/code&gt; for Let’s Encrypt with a Cloudflare DNS-01 solver:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cert-manager.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ClusterIssuer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;letsencrypt-dns01&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;acme&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ops@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;privateKeySecretRef&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;letsencrypt-dns01&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;https://acme-v02.api.letsencrypt.org/directory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;solvers&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;dns01&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cloudflare&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiTokenSecretRef&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;api-token&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;              &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cloudflare-api-token&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:  name: letsencrypt-dns01spec:  acme:    email: ops@example.com    privateKeySecretRef:      name: letsencrypt-dns01    server: https://acme-v02.api.letsencrypt.org/directory    solvers:      - dns01:          cloudflare:            apiTokenSecretRef:              key: api-token              name: cloudflare-api-token&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In the Stack Builder, you drop that manifest in, draw an edge from cert-manager to it, and you’re done. No App-of-Apps incantations or Helm subcharts wrapping a CRD. The AI scaffolds the CRD, suggests the wiring, and explains the solver. It just can’t apply it for you.&lt;/p&gt;
&lt;h2 id=&quot;standardisation-by-cloning-not-copy-paste&quot;&gt;Standardisation by Cloning, Not Copy-Paste&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#standardisation-by-cloning-not-copy-paste&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The fastest way to standardise an environment is to stop building it twice. Ankra’s Clone to Cluster promotes a hardened stack to any environment (dev, staging, production) with its dependency graph and Helm values intact. Variables resolve per environment automatically: the same template renders with &lt;code&gt;app.example.com&lt;/code&gt; in production and &lt;code&gt;app.staging.example.com&lt;/code&gt; in staging. One template, many clusters, zero forked YAML.&lt;/p&gt;
&lt;p&gt;The cloned stack also lands as a draft. A human reviews variable resolution, encryption status, and deployment order in the target cluster before anything runs.&lt;/p&gt;
&lt;h2 id=&quot;the-ai-as-a-teaching-layer&quot;&gt;The AI as a Teaching Layer&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-ai-as-a-teaching-layer&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is what turns “non-technical people can ship” from a marketing gimmick into reality.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/ai-chat.webp&quot; alt=&quot;AI Assistant: page-aware, Stack-aware, tied back to the same surface humans edit&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The AI Assistant (&lt;code&gt;Cmd+J&lt;/code&gt;) is page- and Stack-aware. Open a crashing pod, ask “why?”, and the AI instantly references the logs, manifests, recent events, and the specific Stack change that introduced the issue. It explains the failure in plain English and links the fix directly to the offending Stack values.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proactive Insights:&lt;/strong&gt; Each AI insight includes a confidence score, root-cause analysis, and conversation starters. When resolved, the platform captures a before/after health snapshot, training your team’s custom knowledge base.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Incident Reports:&lt;/strong&gt; For alert-triggered events, AI triangulates timelines, pods, and logs to produce a written incident report readable by managers who have never run kubectl.&lt;/p&gt;
&lt;p&gt;Across all surfaces, the AI documents and explains. A developer who isn’t a Kubernetes expert becomes a self-sufficient operator; a non-engineer becomes a credible reviewer.&lt;/p&gt;
&lt;h2 id=&quot;true-self-service&quot;&gt;True Self-Service&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#true-self-service&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Once the AI acts as a teacher and every change defaults to a draft, your access model can safely relax.&lt;/p&gt;
&lt;p&gt;Members get scoped Kubernetes access; clients and auditors get Read-Only. A QA lead can verify a feature in staging without a kubeconfig. When deeper access is needed, Pod Terminal opens an in-browser shell to any container, gated by cluster health. DevOps can debug a teammate’s local OrbStack cluster through the platform with zero visibility into their actual local filesystem.&lt;/p&gt;
&lt;p&gt;This is what self-service actually means: a production-grade platform that doesn’t require kubeconfigs, VPNs, or Slack hostage situations to drive.&lt;/p&gt;
&lt;h2 id=&quot;why-this-cant-delete-your-database&quot;&gt;Why This Can’t Delete Your Database&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#why-this-cant-delete-your-database&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Four guardrails compose into the answer, directly neutralizing the specific failure modes seen in recent AI incidents.&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Guardrail&lt;/th&gt;&lt;th&gt;How It Prevents Catastrophe&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Drafts&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Every AI change lands as a draft or PR. Replit’s agent had no separation between “propose” and “apply.” Ankra’s AI operates exclusively on proposals.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;GitOps&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Every approved change is a Git commit. Rollback is a simple &lt;code&gt;git revert&lt;/code&gt;, not a postmortem with fabricated logs. The audit trail is immutable to the AI.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Scope&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;The AI acts strictly through Stack values and manifests, not arbitrary &lt;code&gt;kubectl&lt;/code&gt; blasts or &lt;code&gt;terraform destroy&lt;/code&gt; commands.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Identity&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;SOPS-encrypted secrets, RBAC, and sandboxes limit the AI to exactly what the human is allowed to do. It never holds raw cloud root credentials.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;These aren’t “trust the model” features. They are “remove the blast radius” mechanics. The agent gets to be immensely useful precisely because it is physically incapable of being reckless.&lt;/p&gt;
&lt;h2 id=&quot;the-next-generation-of-operations&quot;&gt;The Next Generation of Operations&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-next-generation-of-operations&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The leap isn’t a smarter model. The leap is a platform shape that allows a smart model to be useful without being dangerous. Independent developers, a senior DevOps agent on call, and boring safety rails underneath. That combination allows a five-person team to compete with a thirty-person platform team. It is also what makes “let the AI do it” something a CTO can actually sign off on without losing sleep.&lt;/p&gt;
&lt;p&gt;Ankra’s AI Agent has all the tools to build. The reason it won’t break production is that it has to write everything down, on a draft, in your repo, with your name on the merge button.&lt;/p&gt;
&lt;p&gt;That is the contract. Take it for a spin.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Get started: &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Create a free account on Ankra&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt; | &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mattias Åsell</dc:creator><category>AI</category><category>GitOps</category><category>Platform Engineering</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Komodor vs Ankra: Observe Your Kubernetes, or Operate It?</title><link>https://ankra.ai/blog/komodor-vs-ankra</link><guid isPermaLink="true">https://ankra.ai/blog/komodor-vs-ankra</guid><description>Komodor&apos;s Klaudia is a good AI SRE. Ankra is the next step: an AI that operates the full lifecycle of your apps and infrastructure, runs on any Kubernetes you bring, and keeps Git as the source of truth. Here&apos;s the honest comparison.</description><pubDate>Fri, 17 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;&lt;strong&gt;Prefer to listen?&lt;/strong&gt; Here is Mark reading the post.&lt;/p&gt;
&lt;audio controls preload=&quot;metadata&quot; src=&quot;https://ankra-vod.fsn1.your-objectstorage.com/docs/blog_komodor_vs_ankra_mark_voice.mp3&quot;&gt;&lt;p&gt;Your browser does not support the audio element. &lt;a href=&quot;https://ankra-vod.fsn1.your-objectstorage.com/docs/blog_komodor_vs_ankra_mark_voice.mp3&quot;&gt;Download the MP3&lt;/a&gt; instead.&lt;/p&gt;&lt;/audio&gt;
&lt;p&gt;Komodor’s Klaudia is a serious product. It is an agentic AI SRE that correlates events, changes, and logs across your Kubernetes clusters, uses a versioned topology graph to ground its reasoning, and produces evidence-backed root-cause analysis for things like CrashLoopBackOffs and OOMKills. I want to be upfront about that, because the most common thing I hear from teams evaluating AI-native Kubernetes platforms is “we looked at Komodor, they have Klaudia, what does Ankra actually add?”&lt;/p&gt;
&lt;p&gt;The honest answer is: Komodor’s AI observes your Kubernetes. Ankra’s AI operates it. That difference is not marketing. It is architectural, and once you see it, you cannot unsee it. The rest of this post unpacks what that means in practice, and why the teams I work with keep choosing Ankra even when Komodor technically has an AI SRE too.&lt;/p&gt;
&lt;h2 id=&quot;the-two-philosophies-side-by-side&quot;&gt;The two philosophies, side by side&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-two-philosophies-side-by-side&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Both products start from the same correct observation: Kubernetes incidents are a topology problem, not a log problem. You cannot diagnose a CrashLoopBackOff by reading lines of stderr. You have to walk a graph of services, dependencies, and recent changes. Both products build that graph, and both run AI agents on top of it. So far, we agree.&lt;/p&gt;
&lt;p&gt;Where the paths split is on what the graph contains, and what the AI is allowed to do with it.&lt;/p&gt;
&lt;p&gt;Komodor’s graph is a Kubernetes-native topology. It reads your clusters, tracks the objects Kubernetes exposes, correlates changes to those objects, and asks its AI to reason about them. It is a very good version of that idea, and if your operational model is “someone else delivers changes, we observe them and respond to incidents,” it fits. By design it is SaaS-only, and by design it focuses on the Kubernetes layer. Managed databases, cross-cloud networking, and most of the software installed on top of your cluster live outside its scope.&lt;/p&gt;
&lt;p&gt;Ankra’s graph is the full application and infrastructure lifecycle. Clusters are nodes, yes, but so are Helm addons, manifests, credentials, stacks, applications, CI/CD pipelines, GitHub repositories, and the dependencies that tie them together. The AI that reads that graph is the same engine that built it. It does not just recommend a fix. It writes the change back to Git, reconciles the stack, and watches the rollout through its own preview and readiness model. It treats “understand an incident” and “ship a stack” and “onboard a new service” as the same problem, because in the graph they are.&lt;/p&gt;
&lt;p&gt;That is the sentence to hold onto: Komodor’s AI is downstream of your delivery system. Ankra’s AI is your delivery system.&lt;/p&gt;
&lt;h2 id=&quot;what-operate-means-concretely&quot;&gt;What “operate” means, concretely&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-operate-means-concretely&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When I say Ankra’s AI operates rather than observes, I mean a specific set of capabilities that only make sense if the AI is native to the platform that owns the lifecycle.&lt;/p&gt;
&lt;p&gt;It designs stacks with you. When a developer imports a Helm chart they have never seen, Ankra’s AI reads the chart, the graph, and the existing stack, and tells them which values are safe to change, which are load-bearing, what dependencies they will pull in, and what the deploy order looks like. It proposes the wiring, previews the plan, and asks for confirmation. This is not an SRE feature. It is a platform-engineering feature, and it exists because the AI has access to the same Stack Builder the humans use.&lt;/p&gt;
&lt;p&gt;It manages the lifecycle of the software you install on Kubernetes. When you upgrade cert-manager, the AI knows every stack that depends on it, what the release notes say, what defaults changed, and which of your services are affected by the change. When a Prometheus addon starts consuming more memory than it should, the AI proposes a retention or resource-limit change directly against the addon’s values file, opens the PR, and reconciles. Helm addons, manifests, and their dependencies are first-class citizens of the graph, not just objects observed in-cluster.&lt;/p&gt;
&lt;p&gt;It investigates incidents with all that context in hand. Because the AI knows which PR shipped what Helm value change to which cluster at what time, and which credential each service consumes, and which addon each sidecar belongs to, its root-cause analysis is not a guess based on Kubernetes events. It is a read of the same lifecycle data the platform used to produce the incident in the first place. When it proposes a fix, the fix is a stack change, not a kubectl command. It flows through GitOps with a full audit trail and a one-click rollback. You do not lose any of the safety of GitOps to gain the speed of AI. You get both.&lt;/p&gt;
&lt;p&gt;Proactive insights run continuously against the graph, not just when something is on fire. Ankra’s AI scans every cluster on an adaptive schedule (every sixty seconds when critical issues are active, every ten minutes when the cluster is healthy) and surfaces drift, resource trends, vulnerable addon versions, and capacity risks before they become pages. When you resolve an insight, the resolution gets captured with a before-and-after health snapshot, and the AI indexes the fix into its knowledge base so the next similar incident gets better guidance. It learns from your team’s resolutions, not just from a vendor’s training set.&lt;/p&gt;
&lt;p&gt;Komodor’s Klaudia does parts of the incident-investigation piece very well. It does not do any of the rest, because the rest requires owning the lifecycle.&lt;/p&gt;
&lt;h2 id=&quot;scenario-one-it-works-in-staging-but-breaks-in-prod&quot;&gt;Scenario one: “it works in staging but breaks in prod”&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#scenario-one-it-works-in-staging-but-breaks-in-prod&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Amir ships a feature on a Monday. It looks perfect in staging. Tuesday morning, it is live in production, and customers are complaining that search results are empty. He opens his dashboard tool. The pod is healthy. No restarts. No errors in the obvious places. The app logs show a flurry of “typesense: unauthorized.” He goes to ask James, the DevOps engineer, who is in a meeting. He waits.&lt;/p&gt;
&lt;p&gt;In a Komodor-centric shop, Klaudia eventually helps. It pulls the event history, notices the auth failures, and points at the Typesense integration. But the thing that actually broke is not in the Kubernetes layer. The production Typesense secret was rotated three weeks ago by a compliance automation. The app’s manifest still references the pre-rotation secret name, which has been deleted in prod but still exists in staging, because staging was redeployed later and quietly picked up the rotation. That is three weeks of drift, hiding between environments, invisible until someone shipped a feature that actually used search. An observer-AI can tell you search is failing. Finding the drift is still a human job of diffing environments across two tools.&lt;/p&gt;
&lt;p&gt;In Ankra, Amir never gets to that point. When he hits deploy on the production stack, the platform compares it to staging inside the graph and flags the credential mismatch in the preview, before the deploy even runs. It does not block him, because his change is not the problem, but it surfaces the drift with a one-line explanation: “The Typesense credential referenced by &lt;code&gt;search-service&lt;/code&gt; was rotated in production on March 24. Staging still references the pre-rotation secret. These environments have diverged. Reconcile?” Amir pings James, James reconciles, the feature ships clean.&lt;/p&gt;
&lt;p&gt;This is the kind of thing an observer tool structurally cannot do. It sees each cluster through its own Kubernetes API and has no opinion about whether staging and production are meant to be the same thing. In Ankra, stacks are the first-class object, and a stack deployed to many clusters with different variables is a single lifecycle object in the graph. Drift is not a detective job. It is a diff.&lt;/p&gt;
&lt;h2 id=&quot;scenario-two-the-thursday-why-is-checkout-slow-today-investigation&quot;&gt;Scenario two: the Thursday “why is checkout slow today” investigation&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#scenario-two-the-thursday-why-is-checkout-slow-today-investigation&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At 2:14 PM, checkout p99 latency jumps from 180ms to 820ms. No alert fires yet, because your SLO is 1000ms. But the support team starts hearing complaints, the CEO asks in Slack, and you have about twenty minutes before this becomes a real incident.&lt;/p&gt;
&lt;p&gt;Klaudia, doing its job well, correlates the latency climb with recent cluster changes. It will surface the candidates: the &lt;code&gt;cert-manager&lt;/code&gt; upgrade this morning, the new ingress rule yesterday, the Istio addon upgrade last night. It highlights the Istio upgrade because it has the strongest temporal correlation. A skilled on-call engineer reads the evidence chain, agrees with the correlation, and starts investigating Istio. Total time to resolution in the well-run Komodor flow: maybe twenty to thirty minutes, depending on how fast you can get from “Istio is implicated” to “here is the exact values change that caused this.”&lt;/p&gt;
&lt;p&gt;In Ankra, the AI does the same correlation and then keeps going. Because the Istio addon is a first-class node in the graph, the AI knows which chart version was installed, which value defaults changed between versions, and which sidecars in the mesh depend on it. It pulls the release notes from the addon’s source, finds the &lt;code&gt;meshConfig.defaultConfig.concurrency&lt;/code&gt; default change, correlates that with the sidecar restart pattern, and writes the fix as a specific one-line change to the addon’s values file. Before your p99 hits the SLO threshold, the message in Slack reads: “&lt;code&gt;checkout-api&lt;/code&gt; p99 rising. Root cause is the Istio addon upgrade at 23:14 last night. The new default for &lt;code&gt;meshConfig.defaultConfig.concurrency&lt;/code&gt; is stricter and is causing sidecar connection churn. Recommended fix: pin &lt;code&gt;concurrency: 4&lt;/code&gt; in the Istio addon values, or roll back the addon to the previous version. Apply fix.” You click roll back. It commits, the engine reconciles, p99 settles.&lt;/p&gt;
&lt;p&gt;The difference between the two flows is not intelligence. It is scope. Both AIs are smart enough to find Istio. Only one of them owns the addon lifecycle and can propose a specific values-level fix, because only one of them installed the addon in the first place.&lt;/p&gt;
&lt;h2 id=&quot;scenario-three-the-new-hires-second-week&quot;&gt;Scenario three: the new hire’s second week&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#scenario-three-the-new-hires-second-week&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sofia joined two weeks ago. She is a strong engineer from a company that used Heroku. Her task this week is to add a new microservice: a recommendation API that needs Postgres, Redis, and a vector database.&lt;/p&gt;
&lt;p&gt;In a Komodor-centric shop, her week is mostly blocked on tribal knowledge. She writes the code. She writes a Dockerfile. She copies a Helm chart from another service. She does not know which values are safe to change. She asks in Slack. She waits. She gets staging access. She deploys. She spends three days debugging why her service cannot reach the vector database, because a network policy exists that nobody documented. Two weeks in, she has not shipped. Klaudia, if she ever opens it, can tell her the service is failing to reach the DB. It cannot tell her about the policy that was not on the graph Komodor sees.&lt;/p&gt;
&lt;p&gt;In Ankra, Sofia opens Stack Builder. The AI sees the existing product stack as a graph and her Helm chart as a new node she is trying to add. It tells her, unprompted: “This chart needs a Postgres and a Redis. Both exist in the &lt;code&gt;shared-data&lt;/code&gt; stack. Should I wire the dependencies? Your vector DB is not in the stack yet; here are two options from the addon library with compatible configurations.” She says yes. It sets up the credential bindings, maps the network policies it can see on the graph, and surfaces the one policy that would block her service with a suggested patch. She clicks preview, sees the DAG, deploys to a personal on-demand staging environment that was cloned from the shared stack in about a minute. She iterates for two days, opens a PR, and merges. She ships in her first week.&lt;/p&gt;
&lt;p&gt;The AI is not doing her engineering work. What it erased is the tacit-knowledge tax. In a toolchain where every piece of context lives in a different place and a different person’s head, new engineers take months to become productive. In a platform where the graph is the context, and the AI has read/write access to the graph, the ramp-up question becomes a conversation.&lt;/p&gt;
&lt;h2 id=&quot;bring-your-own-kubernetes-where-the-philosophies-really-separate&quot;&gt;Bring your own Kubernetes: where the philosophies really separate&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#bring-your-own-kubernetes-where-the-philosophies-really-separate&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is the structural difference that decides more deals than any feature on a pitch deck: where the thing runs, and who owns the clusters it manages.&lt;/p&gt;
&lt;p&gt;Komodor is SaaS-only. Your clusters report into Komodor’s cloud. Your topology graph, your change history, and your AI evidence chains live there. That is a reasonable choice for many teams, and it simplifies Komodor’s delivery model. It also means you are renting your observability surface, and you are implicitly trusting a vendor with a real-time feed of your production topology. If you operate in a regulated environment, on an air-gapped edge, or on a cloud provider that Komodor deprioritizes, you bend to fit the tool.&lt;/p&gt;
&lt;p&gt;Ankra is built around the opposite premise: you bring the Kubernetes, we bring the platform. Any cluster from any provider (AWS, GCP, Azure, Hetzner, OVH, UpCloud, bare-metal on-prem, edge locations, air-gapped environments) imports into Ankra through a single Helm install of the Ankra Agent. The agent is the only thing that needs network access, and it is running in your cluster, under your control, with your RBAC. You can also have Ankra provision clusters for you if you want, but that is a choice, not a constraint. The platform genuinely does not care where the cluster lives, as long as it can talk to the agent.&lt;/p&gt;
&lt;p&gt;This matters for three reasons that show up every day in real operations. First, it means the same AI, the same graph, and the same stacks work identically across your hyperscaler production, your on-prem dev clusters, and your edge devices. You are not running two tools to cover two environments. Second, it means you can adopt Ankra inside compliance and sovereignty boundaries that a SaaS-only tool cannot cross. Regulated industries, European data residency, customer-hosted deployments, OEM scenarios. All handled because the execution plane is your cluster. Third, it means your vendor relationship is inverted: Ankra does not own your fleet, you do. Ankra’s engine reads and writes to resources that live in your clusters and your Git repos. You can turn it off tomorrow and your infrastructure keeps running.&lt;/p&gt;
&lt;p&gt;That last point is the one I want to pull apart on its own, because vendor lock-in is quietly the biggest cost of picking the wrong platform, and it is the one nobody brings up during the demo.&lt;/p&gt;
&lt;h2 id=&quot;no-lock-in-git-is-the-source-of-truth-not-ankra&quot;&gt;No lock-in: Git is the source of truth, not Ankra&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#no-lock-in-git-is-the-source-of-truth-not-ankra&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every action Ankra’s engine takes (every stack change, every AI-applied fix, every addon upgrade, every credential binding) gets written back to your Git repository as a commit or a pull request. That is not a nice-to-have integration. It is the architecture. The UI, the Terraform provider, the CLI, the API, and the AI all hit the same engine, and the engine’s output is always Git. The cluster reconciles from Git. Your audit trail lives in Git. Your history lives in Git.&lt;/p&gt;
&lt;p&gt;The practical consequence is that Ankra does not own your environment. You do. If tomorrow you decide Ankra is no longer the right tool, you still have a fully functional GitOps repository describing every stack, every dependency, every value, and every addon. You can point Argo or Flux at it, or you can run &lt;code&gt;helm install&lt;/code&gt; directly, and your workloads keep running. The graph is ours. The state is yours.&lt;/p&gt;
&lt;p&gt;Compare that to the Komodor model, where the graph, the change history, and the AI reasoning all live in Komodor’s SaaS. If you leave, the graph leaves with you only as an export. The continuous record of why things changed, the evidence chains, the learned resolutions. Those are vendor-owned artifacts. This is not a criticism of Komodor, it is a structural feature of a SaaS observability product. But it means the cost of switching rises every quarter you stay, because every quarter more of your operational knowledge accumulates inside the vendor’s system.&lt;/p&gt;
&lt;p&gt;Ankra’s accumulation goes the other way. The longer you run Ankra, the richer your Git history gets and the better your stack model becomes. The AI’s learned resolutions are indexed into an insight knowledge base scoped to your organization, yes, but the changes the AI made live in your Git commits, under your authorship, with your review process. There is no moment where leaving Ankra loses you something your infrastructure needs.&lt;/p&gt;
&lt;p&gt;If you are choosing a platform you expect to run for five or ten years, “what do I still have if this vendor goes away” is the question that matters most. With Ankra, the answer is “everything.”&lt;/p&gt;
&lt;h2 id=&quot;where-komodor-is-still-a-fine-answer&quot;&gt;Where Komodor is still a fine answer&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#where-komodor-is-still-a-fine-answer&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I want to stay fair. If your organization has deliberately chosen to keep delivery and operations in separate tools owned by separate teams, Komodor is a defensible pick for the ops half. It is a polished product with a real AI offering, real users, and real value inside its niche. If you are happy with your existing Argo or Flux setup, your existing Terraform, and your existing stack ownership, and you just want a smarter pane of glass on top, Klaudia will do a better job than nothing.&lt;/p&gt;
&lt;p&gt;But if you are asking the bigger question of what the next decade of Kubernetes operations looks like, dashboard-and-observer is not it. The next decade is an AI that owns the lifecycle of your applications, your infrastructure, and the solutions installed on your clusters, grounded in a graph the AI itself maintains, operating on any Kubernetes you bring, and writing every change back to your own Git. That is the direction of travel, and that is what Ankra is built around.&lt;/p&gt;
&lt;h2 id=&quot;what-a-migration-actually-looks-like&quot;&gt;What a migration actually looks like&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-a-migration-actually-looks-like&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The good news is that moving off a Komodor-centric setup does not require ripping anything out on day one. Install the Ankra Agent with a single Helm command into any existing cluster, and the platform imports it read-only. You immediately get the graph, drift detection, AI Insights, and AI Incidents on top of whatever you already run, without changing a single line of your current delivery pipeline. Run Ankra and Komodor side by side for as long as you want. Most teams do this for two or three weeks, and stop opening the other tab on their own.&lt;/p&gt;
&lt;p&gt;From there, you pick one stack. Import its Helm chart into Stack Builder, let the AI suggest the dependency wiring, preview the plan, and deploy. The engine writes the result back to Git. You keep the audit trail you already had, plus a better one. Once one stack is on the graph, the rest follow, because every addon you bring in makes the AI more useful on the rest of your system.&lt;/p&gt;
&lt;p&gt;The platform respects your existing Git repos, your existing Helm charts, your existing credentials, your existing cloud providers, and your existing on-call culture. It just makes all of them share one model of reality.&lt;/p&gt;
&lt;h2 id=&quot;the-move&quot;&gt;The move&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-move&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Komodor’s AI watches your Kubernetes. Ankra’s AI runs it. Komodor’s platform lives in Komodor’s cloud. Ankra runs on the Kubernetes you already own, wherever it lives, and writes every change back to the Git you already use. Komodor is a good version of the observer generation. Ankra is the operator generation, and the gap between the two is exactly as big as the difference between being told your search is broken and having the drift caught before the deploy goes out.&lt;/p&gt;
&lt;p&gt;The fastest way to feel it is to deploy one stack. &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Start a free account on Ankra&lt;/a&gt;, import any cluster you already run, and let the AI propose its first fix. Keep Komodor in the other tab. You will know which one you want owning your Kubernetes by the end of the week.&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Comparisons</category><category>AI</category><category>Platform Engineering</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>How a 5-Person Team Cloned Production for Local Dev and Never Looked Back</title><link>https://ankra.ai/blog/clone-production-environments-with-stacks</link><guid isPermaLink="true">https://ankra.ai/blog/clone-production-environments-with-stacks</guid><description>A real walkthrough of using Ankra Stacks to clone production-like infrastructure for local development, on-demand staging, QA review, and client demos. From OrbStack on a laptop to GitHub Actions to production.</description><pubDate>Sun, 22 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Last month I watched a team of five ship a feature from a laptop to production in under two days. No Slack threads asking DevOps for help setting up a staging environment. No “it works on my machine” when the PM finally saw it. No three-week wait for QA to get access to a running build.&lt;/p&gt;
&lt;p&gt;They used Ankra Stacks to clone a production-like environment onto a developer’s laptop, iterate locally, push through CI/CD, spin up an on-demand staging environment, hand it to QA and the client for review, and promote to production. Same stack at every stage. Same config. Different variables.&lt;/p&gt;
&lt;p&gt;This is the story of how they did it.&lt;/p&gt;
&lt;h2 id=&quot;the-team&quot;&gt;The team&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-team&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Five people. One backend developer (Priya), one frontend developer (Amir), one DevOps engineer (James), a QA lead (Sofia), and a project manager (Tom). The client wanted a new recommendation engine that needed Redis for caching, PostgreSQL for persistent data, Typesense for search, and HashiCorp Vault and Consul for secrets management and service discovery. The kind of infrastructure that usually takes a week just to agree on the Helm values.&lt;/p&gt;
&lt;h2 id=&quot;monday-morning-i-need-all-of-this-running-on-my-laptop&quot;&gt;Monday morning: “I need all of this running on my laptop”&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#monday-morning-i-need-all-of-this-running-on-my-laptop&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Priya’s application runs natively in her terminal. She writes Go, she runs &lt;code&gt;go run main.go&lt;/code&gt;, she hits endpoints with curl. That is her loop and she is fast at it. What she does not want is to also hand-configure Redis, Postgres, Typesense, Vault, and Consul on her MacBook.&lt;/p&gt;
&lt;p&gt;She has OrbStack running, which gives her a local Kubernetes cluster out of the box. The Ankra Agent gets installed with a single Helm command:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;helm&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;install&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ankra-agent&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;oci://ghcr.io/ankraio/ankra-agent&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;\&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--set&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apiKey=YOUR_API_KEY&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;helm install ankra-agent oci://ghcr.io/ankraio/ankra-agent \  --set apiKey=YOUR_API_KEY&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;That is it. Her local OrbStack cluster appears in the Ankra platform. No tunneling, no port-forward hacks, no custom scripts.&lt;/p&gt;
&lt;h3 id=&quot;building-the-infrastructure-stack&quot;&gt;Building the infrastructure stack&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#building-the-infrastructure-stack&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;James, the DevOps engineer, had already built a production stack in Ankra for their main application. It included Redis, PostgreSQL, Typesense, Vault with Consul as the storage backend, ingress-nginx, and cert-manager. Priya does not need to understand any of that. She goes to &lt;strong&gt;Stacks&lt;/strong&gt;, finds the production stack, clicks the menu, and selects &lt;strong&gt;Clone to Cluster&lt;/strong&gt;, targeting her local OrbStack cluster.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;stacks&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-infra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--to&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;priyas-orbstack&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster stacks clone production-infra --to priyas-orbstack&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The stack arrives as a draft on her local cluster. She can review every addon and manifest before deploying. The stack variables automatically resolve to local values: the ingress domain switches from &lt;code&gt;app.company.com&lt;/code&gt; to &lt;code&gt;localhost&lt;/code&gt;, resource limits scale down to fit a laptop, and replica counts drop to 1.&lt;/p&gt;
&lt;p&gt;She clicks deploy. Ankra’s engine resolves the dependency graph, deploys the namespace first, then Consul, then Vault (which depends on Consul as its storage backend), then PostgreSQL, then Redis, then Typesense. Five minutes later, everything is running.&lt;/p&gt;
&lt;h3 id=&quot;it-works-out-of-the-box&quot;&gt;It works out of the box&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#it-works-out-of-the-box&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Priya runs her application natively in her terminal with &lt;code&gt;go run main.go&lt;/code&gt;. Her app connects to Redis on &lt;code&gt;localhost:6379&lt;/code&gt;, Postgres on &lt;code&gt;localhost:5432&lt;/code&gt;, Typesense on &lt;code&gt;localhost:8108&lt;/code&gt;. OrbStack exposes Kubernetes services to localhost automatically, so there is no manual port-forwarding needed. No Docker Compose file. No &lt;code&gt;kubectl port-forward&lt;/code&gt; running in five separate tabs. No “let me check if the ports conflict with something else.” She writes code, saves, and her application talks to production-grade infrastructure running in Kubernetes on her own machine.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;If services are not reachable on localhost, check that &lt;strong&gt;Expose services to local network devices&lt;/strong&gt; is enabled in OrbStack settings.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The infrastructure is identical to what runs in production. Same Helm charts. Same configuration structure. Same dependency wiring between Vault and Consul. The only things that differ are the variables: domain names, replica counts, resource limits, TLS settings. The blueprint is the same.&lt;/p&gt;
&lt;h2 id=&quot;monday-afternoon-the-redis-authentication-problem&quot;&gt;Monday afternoon: The Redis authentication problem&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#monday-afternoon-the-redis-authentication-problem&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Priya’s app connects to Redis but gets an authentication error. The production stack requires a password, but she does not know what it is or where to set it.&lt;/p&gt;
&lt;p&gt;She opens the Ankra AI assistant with &lt;code&gt;Cmd+J&lt;/code&gt; and types:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“My app can’t connect to Redis. I’m getting an auth error on my local cluster.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The AI assistant knows her cluster state. It can see the Redis addon, its Helm values, and the Kubernetes resources it created. It responds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“Your Redis deployment has &lt;code&gt;auth.existingSecret&lt;/code&gt; configured, pointing to a Kubernetes Secret called &lt;code&gt;redis-credentials&lt;/code&gt;. This secret has a key &lt;code&gt;redis-password&lt;/code&gt; that was auto-generated when the stack was deployed. You can retrieve it with:&lt;/p&gt;
&lt;p&gt;&lt;code&gt;kubectl get secret redis-credentials -n infra -o jsonpath=&amp;#39;{.data.redis-password}&amp;#39; | base64 -d&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;Alternatively, you can set a known password by adding a stack variable &lt;code&gt;REDIS_PASSWORD&lt;/code&gt; and mapping it in your Redis addon values.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;She grabs the password, sets it in her &lt;code&gt;.env&lt;/code&gt; file, and her app connects immediately.&lt;/p&gt;
&lt;h3 id=&quot;the-ingress-class-mismatch&quot;&gt;The ingress class mismatch&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-ingress-class-mismatch&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;But there is a second issue. She cloned the production stack, and production uses an ingress class called &lt;code&gt;nginx-external&lt;/code&gt; for their cloud load balancer. Her local OrbStack cluster only has the default &lt;code&gt;nginx&lt;/code&gt; ingress class.&lt;/p&gt;
&lt;p&gt;She asks the AI:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“My ingress resources are not routing traffic. Everything shows as not found.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The AI responds:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The ingress resources in your stack are configured with &lt;code&gt;ingressClassName: nginx-external&lt;/code&gt;, but your local cluster only has the &lt;code&gt;nginx&lt;/code&gt; ingress class available. You should update the &lt;code&gt;ingressClassName&lt;/code&gt; in your stack’s ingress manifests to &lt;code&gt;nginx&lt;/code&gt;. You can do this with a stack variable:&lt;/p&gt;
&lt;p&gt;Set a cluster-level variable &lt;code&gt;INGRESS_CLASS=nginx&lt;/code&gt; on your local cluster, and update the ingress manifests to use &lt;code&gt;${{ ankra.INGRESS_CLASS }}&lt;/code&gt;. This way, each environment resolves to the correct ingress class automatically.”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;She adds the variable, updates the manifest, and traffic routes correctly. The AI caught what would have been an hour of debugging in kubectl logs.&lt;/p&gt;
&lt;p&gt;This is the pattern that makes Stacks powerful for local development. You clone the production blueprint, and the AI assistant helps you identify the handful of values that need to change for your local environment. After the first clone, those variables are saved. Next time, it just works.&lt;/p&gt;
&lt;h2 id=&quot;monday-evening-devops-can-help-without-leaving-their-desk&quot;&gt;Monday evening: DevOps can help without leaving their desk&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#monday-evening-devops-can-help-without-leaving-their-desk&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Priya hits a more complicated problem. Vault is not initializing correctly on her local cluster. She is not a Vault expert, and the logs are dense.&lt;/p&gt;
&lt;p&gt;She messages James: “Vault is failing to start on my local. Can you take a look?”&lt;/p&gt;
&lt;p&gt;James does not need to walk over to her desk, SSH into her machine, or ask her to copy-paste logs into Slack. He opens the Ankra platform, navigates to Priya’s OrbStack cluster, and he is looking at the same infrastructure she is. He can see the Vault pods, their logs, their events, the Consul backend status, the Helm values. He opens a &lt;strong&gt;Pod Terminal&lt;/strong&gt; directly in the Ankra UI, selects the Vault container, and drops into a shell.&lt;/p&gt;
&lt;p&gt;He finds the issue: the Consul storage backend address in the Vault config has a hardcoded production namespace. He updates the Helm values in the stack to use &lt;code&gt;${{ ankra.CONSUL_NAMESPACE }}&lt;/code&gt;, sets the variable to &lt;code&gt;infra&lt;/code&gt; on Priya’s cluster, and redeploys. Vault starts.&lt;/p&gt;
&lt;p&gt;Here is what matters about this interaction: James had &lt;strong&gt;full control&lt;/strong&gt; over the Kubernetes environment on Priya’s laptop, but he was completely &lt;strong&gt;isolated&lt;/strong&gt; to the Kubernetes cluster. He could not access her filesystem, her code, her browser history. He operated inside the Kubernetes boundary and nothing else. For a small team where everyone wears multiple hats, this balance between helpfulness and isolation is critical. DevOps can unblock developers in minutes, and developers do not need to hand over their whole machine.&lt;/p&gt;
&lt;h2 id=&quot;tuesday-morning-push-to-github-let-ci-handle-it&quot;&gt;Tuesday morning: Push to GitHub, let CI handle it&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#tuesday-morning-push-to-github-let-ci-handle-it&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Priya’s feature works locally. Her Go application talks to Redis, Postgres, Typesense, and Vault, all running in her OrbStack Kubernetes cluster. Time to get it into the real pipeline.&lt;/p&gt;
&lt;p&gt;She pushes her application code to a feature branch. Amir pushes the frontend changes to the same branch. Their GitHub Actions workflow kicks in:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Build and Deploy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;branches&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: [&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;feature/*&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;jobs&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;build&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;runs-on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;steps&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;actions/checkout@v4&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;uses&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;docker/build-push-action@v5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;with&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;push&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;tags&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ghcr.io/company/recommendation-engine:${{ github.sha }}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;update-gitops&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;needs&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;build&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;runs-on&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ubuntu-latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;steps&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Clone GitOps repo&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;git clone git@github.com:company/gitops-config.git gitops&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Update image tag&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;working-directory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;gitops&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;sed -i &amp;quot;s|image:.*|image: ghcr.io/company/recommendation-engine:${{ github.sha }}|&amp;quot; \&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;            &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;clusters/dev-cluster/manifests/recommendation-deployment.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Push to GitOps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;working-directory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;gitops&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;run&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;git add .&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;git commit -m &amp;quot;deploy: recommendation-engine ${{ github.sha }}&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;          &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;git push&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;name: Build and Deployon:  push:    branches: [feature/*]jobs:  build:    runs-on: ubuntu-latest    steps:      - uses: actions/checkout@v4      - uses: docker/build-push-action@v5        with:          push: true          tags: ghcr.io/company/recommendation-engine:${{ github.sha }}  update-gitops:    needs: build    runs-on: ubuntu-latest    steps:      - name: Clone GitOps repo        run: git clone git@github.com:company/gitops-config.git gitops      - name: Update image tag        working-directory: gitops        run: |          sed -i &amp;quot;s|image:.*|image: ghcr.io/company/recommendation-engine:${{ github.sha }}|&amp;quot; \            clusters/dev-cluster/manifests/recommendation-deployment.yaml      - name: Push to GitOps        working-directory: gitops        run: |          git add .          git commit -m &amp;quot;deploy: recommendation-engine ${{ github.sha }}&amp;quot;          git push&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The GitHub Action builds the container image, pushes it to GHCR, and updates the manifest in the GitOps repository. Ankra detects the change in the connected Git repository and triggers ArgoCD on the dev cluster. The new image rolls out automatically.&lt;/p&gt;
&lt;p&gt;This is the same GitOps flow the team uses for every service. The infrastructure stack (Redis, Postgres, Typesense, Vault, Consul) is already running on the dev cluster because James cloned the same production stack there weeks ago. Priya’s application code deploys into that existing infrastructure. No new Helm values to write. No infra tickets to file.&lt;/p&gt;
&lt;h2 id=&quot;tuesday-afternoon-on-demand-staging&quot;&gt;Tuesday afternoon: On-demand staging&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#tuesday-afternoon-on-demand-staging&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The feature works on the dev cluster. Now it needs to go to staging for formal testing. James clones the same infrastructure stack from the dev cluster to staging:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;stacks&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-infra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--to&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;staging-cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster stacks clone production-infra --to staging-cluster&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The staging cluster has its own set of variables: &lt;code&gt;staging.company.com&lt;/code&gt; for the domain, higher resource limits than local but lower than production, staging TLS certificates, a staging-specific Vault token. The stack arrives as a draft. James reviews the manifests, confirms the variable resolution looks correct, and deploys.&lt;/p&gt;
&lt;p&gt;The application deployment follows the same pattern. The GitHub Actions workflow runs against the staging branch, updates the GitOps repo for the staging cluster, and ArgoCD syncs it. Within minutes, the recommendation engine is running in staging with the full infrastructure stack behind it.&lt;/p&gt;
&lt;p&gt;Everything committed to Git. Every addon, every manifest, every variable override. If something goes wrong, they can diff staging against dev and see exactly what changed. No tribal knowledge required.&lt;/p&gt;
&lt;h2 id=&quot;tuesday-afternoon-qa-gets-access&quot;&gt;Tuesday afternoon: QA gets access&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#tuesday-afternoon-qa-gets-access&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sofia, the QA lead, needs to test the recommendation engine in staging. In the old world, this meant asking James to set up port-forwarding, share credentials, or create a VPN connection. That conversation alone could burn half a day.&lt;/p&gt;
&lt;p&gt;With Ankra, James opens the organisation settings, clicks &lt;strong&gt;Add User&lt;/strong&gt;, types Sofia’s email, and assigns her the &lt;strong&gt;Member&lt;/strong&gt; role. That is it.&lt;/p&gt;
&lt;p&gt;Sofia logs in and sees the staging cluster. She can browse the running workloads, check pod logs, view the stack configuration, and access the application through the staging domain. She does not need kubectl. She does not need cluster credentials. She does not need to understand Helm charts.&lt;/p&gt;
&lt;p&gt;She finds a bug: the search results are not returning in the expected order. She opens the Ankra AI assistant and asks:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;“The recommendation-engine pods are returning search results in the wrong order. Can you check the Typesense configuration?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The AI assistant examines the Typesense addon’s Helm values, the pod logs, and the resource state. It identifies that the sort order configuration in the Typesense values differs from what the application expects. Sofia copies the AI’s findings into a bug report and assigns it to Priya.&lt;/p&gt;
&lt;h2 id=&quot;tuesday-late-afternoon-the-client-sees-it-before-production&quot;&gt;Tuesday late afternoon: The client sees it before production&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#tuesday-late-afternoon-the-client-sees-it-before-production&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Tom, the PM, has a demo with the client at 4pm. The client wants to see the recommendation engine working before they approve the production rollout.&lt;/p&gt;
&lt;p&gt;Tom asks James to add the client to the platform. James opens the organisation settings, adds the client’s email, and assigns them &lt;strong&gt;Read-only&lt;/strong&gt; access.&lt;/p&gt;
&lt;p&gt;The client opens the Ankra platform and sees the staging environment. They can view the application, see that the infrastructure is running, and verify the feature works as expected. They cannot modify anything. They cannot deploy. They cannot see secrets. They get just enough visibility to say “yes, ship it.”&lt;/p&gt;
&lt;p&gt;Tom does not need to record a demo video. He does not need to schedule a screen share. The client sees the live staging environment, running the actual code, backed by the actual infrastructure. They approve.&lt;/p&gt;
&lt;h2 id=&quot;wednesday-production&quot;&gt;Wednesday: Production&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#wednesday-production&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The stack has been tested locally on Priya’s OrbStack, validated on the dev cluster, verified by QA on staging, and approved by the client. Time for production.&lt;/p&gt;
&lt;p&gt;James clones the stack from staging to the production cluster:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;stacks&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-infra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--to&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;ankra cluster stacks clone production-infra --to production-cluster&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;The stack arrives as a draft. Production variables resolve: the real domain, production TLS certificates, higher replica counts, production Vault tokens with tighter policies, production Consul ACLs. James reviews every manifest in draft mode. Nothing touches the production cluster until he clicks deploy.&lt;/p&gt;
&lt;p&gt;The application deployment follows the same GitHub Actions flow, this time triggered by a merge to main. The image deploys, ArgoCD syncs, and the recommendation engine is live.&lt;/p&gt;
&lt;p&gt;Total time from “I need this running on my laptop” to production: under two days. Four environments. One stack template. Zero YAML copying.&lt;/p&gt;
&lt;h2 id=&quot;what-made-this-work&quot;&gt;What made this work&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-made-this-work&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;Stacks as the unit of infrastructure.&lt;/strong&gt; Not individual Helm charts scattered across repos. Not Terraform modules that take 30 minutes to plan. A Stack groups everything the application needs: Redis, Postgres, Typesense, Vault, Consul, ingress, certificates, namespaces. Clone the stack, and you clone the entire environment.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Variables at every level.&lt;/strong&gt; Organisation defaults, cluster overrides, stack overrides. The same stack template runs everywhere. The domain name, the replica count, the ingress class, the resource limits are all just variables that resolve differently per cluster.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The AI assistant that knows your cluster.&lt;/strong&gt; Not a generic chatbot. The AI sees your addons, your manifests, your Helm values, your pod logs. When Priya cloned the production stack and Redis auth failed, the AI did not give her a generic Redis troubleshooting guide. It told her exactly which secret to look at and exactly which variable to set. When the ingress class was wrong, it told her exactly which field to change and suggested the variable pattern to make it permanent.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;DevOps access that is helpful and isolated.&lt;/strong&gt; James could debug Vault on Priya’s laptop through the Ankra UI. He had full control over the Kubernetes environment, pod terminals, logs, Helm values, redeployments. But he was sandboxed inside the Kubernetes boundary. He could not access Priya’s code, her files, or anything outside the cluster. Full control where it matters. Complete isolation everywhere else.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Git as the source of truth.&lt;/strong&gt; Every clone, every variable change, every deployment is committed to the GitOps repository. When Tom shows the staging environment to the client, there is a Git commit that represents exactly what is running. When they promote to production, they can diff the two and see exactly what changed. Auditors love this. Developers love this more, because it means they can understand any environment by reading a repo.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GitHub Actions as the CI glue.&lt;/strong&gt; The team did not replace their CI pipeline. They kept GitHub Actions for building images and updating manifests. Ankra handles the infrastructure and the GitOps sync. The two systems work together without stepping on each other.&lt;/p&gt;
&lt;h2 id=&quot;clone-dont-recreate&quot;&gt;Clone, don’t recreate&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#clone-dont-recreate&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The real unlock is that Priya never built the infrastructure stack. James built it once for production. He had already cloned it to the dev cluster weeks earlier. Priya cloned it to her laptop. The AI assistant helped her adjust the two or three values that differ between production and a local environment. Then James cloned it to staging, and then to production. Each time the stack carried its dependency graph, its Helm values, its manifests. Each time the variables resolved for the target environment.&lt;/p&gt;
&lt;p&gt;This is what “production-like” actually means. Not a docker-compose.yml that vaguely resembles production. Not a README with 47 steps to set up a local environment. The actual production stack, running on Kubernetes, with the actual dependency wiring, adjusted for local constraints through variables.&lt;/p&gt;
&lt;p&gt;If your team is still copying YAML between environments, still writing setup guides that nobody follows, still asking “does staging have the same Redis version as prod?”, try cloning a stack. It takes five minutes. And it works out of the box.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Join our community: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Slack&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt;, &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Stacks</category><category>Developer Experience</category><category>CI/CD</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Kubernetes on the Edge: One Platform to Rule Them All</title><link>https://ankra.ai/blog/kubernetes-on-the-edge</link><guid isPermaLink="true">https://ankra.ai/blog/kubernetes-on-the-edge</guid><description>Edge Kubernetes is exploding, but our operational tooling has not kept up. Here is how Ankra delivers a true single pane of glass combining AI-powered troubleshooting, native GitOps, and stack cloning to turn weeks of cluster setup into minutes.</description><pubDate>Thu, 05 Mar 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Picture your current infrastructure footprint. You probably have a dozen clusters: three in the cloud, two on-prem, and seven sitting at the edge, running on hardware you can not SSH into without navigating a VPN configured by someone who left the company two years ago.&lt;/p&gt;
&lt;p&gt;Each cluster has its own &lt;code&gt;kubectl&lt;/code&gt; context. Its own ArgoCD instance. Its own set of Grafana dashboards suffering from alert fatigue. And its own sprawling mess of GitHub Actions workflows that took half a day each to wire up.&lt;/p&gt;
&lt;p&gt;Every time the business needs a new edge cluster, you lose an engineer for a day just copying, pasting, and tweaking CI/CD pipelines. You lose an afternoon debugging GitOps repo access. You lose a morning untangling Helm value drift between staging and the new site.&lt;/p&gt;
&lt;p&gt;This is the reality of Kubernetes at the edge in 2026. The orchestrator itself won the war. The tooling around it is still stuck in the trenches of 2020.&lt;/p&gt;
&lt;h2 id=&quot;the-edge-problem-no-one-wants-to-acknowledge&quot;&gt;The Edge Problem No One Wants to Acknowledge&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-edge-problem-no-one-wants-to-acknowledge&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Kubernetes is universally adaptable. K3s and MicroK8s proved we can run it on a Raspberry Pi. But our operational tooling, the dashboards, delivery pipelines, and observability stacks, was built for a centralized world. It assumes you have one to three massive cloud clusters managed by a dedicated platform team.&lt;/p&gt;
&lt;p&gt;Edge computing shatters that assumption.&lt;/p&gt;
&lt;p&gt;Whether it is a logistics company running K3s in 50 warehouses, a telecom managing cell tower nodes, or a retail chain with a cluster in every store, the problem is not &lt;em&gt;running&lt;/em&gt; Kubernetes at the edge. The problem is managing the resulting sprawl at scale:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Observability Blindness:&lt;/strong&gt; You can not run a separate monitoring stack per site. Nobody is going to check 50 different Grafana endpoints.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Delivery Bottlenecks:&lt;/strong&gt; Hand-crafting GitHub Actions for every cluster does not scale. Past 10 clusters, it becomes a full-time job.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Troubleshooting Friction:&lt;/strong&gt; You can not expect a retail store developer to run &lt;code&gt;kubectl describe pod&lt;/code&gt; and interpret scheduling events.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration Drift:&lt;/strong&gt; Manually ensuring every site runs the exact same stack versions is a fast track to staging/production parity nightmares.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Time-to-Value:&lt;/strong&gt; The business expects a new site live in hours, not the week it currently takes to provision the operational plumbing.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;redefining-the-single-pane-of-glass&quot;&gt;Redefining the “Single Pane of Glass”&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#redefining-the-single-pane-of-glass&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;“Single pane of glass” has devolved into a vendor buzzword for slapping a React dashboard on top of the Kubernetes API.&lt;/p&gt;
&lt;p&gt;A true single pane of glass means one interface to observe, deploy, troubleshoot, and govern &lt;em&gt;every&lt;/em&gt; cluster you operate, regardless of its physical location or network topology. Here is how Ankra makes that a reality.&lt;/p&gt;
&lt;h3 id=&quot;import-any-cluster-in-under-five-minutes&quot;&gt;Import Any Cluster in Under Five Minutes&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#import-any-cluster-in-under-five-minutes&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Whether it is an EKS cluster in Frankfurt or a MicroK8s node in a Gothenburg warehouse, bringing a cluster into Ankra requires zero network engineering.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Name your cluster in the Ankra dashboard.&lt;/li&gt;
&lt;li&gt;Run a single Helm command on the target cluster.&lt;/li&gt;
&lt;li&gt;Watch the cluster appear in your dashboard.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;There is no complex inbound networking, no new firewall rules, and no VPN requirement. The lightweight Ankra Agent establishes a secure outbound connection. Within minutes, you have centralized visibility into workloads, configs, RBAC, and events.&lt;/p&gt;
&lt;p&gt;Compare that to the traditional integration tax: configuring &lt;code&gt;kubeconfig&lt;/code&gt;, setting up Prometheus/Grafana, deploying Loki, configuring ArgoCD, and wiring up Git repos. That is days of toil for a senior engineer. Ankra reduces it to minutes.&lt;/p&gt;
&lt;h3 id=&quot;unified-resource-browsing&quot;&gt;Unified Resource Browsing&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#unified-resource-browsing&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Once connected, Ankra abstracts away context switching. You can navigate Deployments, StatefulSets, DaemonSets, and ConfigMaps across your entire fleet from one unified browser.&lt;/p&gt;
&lt;p&gt;Need to restart a deployment on a remote edge node? Click a button. Need to scale replicas? Update the value. Need to exec into a container? Open the built-in pod terminal right from your browser. For edge deployments where direct SSH access is a security risk or physically impossible, this is not a luxury. It is a baseline requirement for incident response.&lt;/p&gt;
&lt;h2 id=&quot;escaping-pipeline-spaghetti-with-native-gitops&quot;&gt;Escaping Pipeline Spaghetti with Native GitOps&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#escaping-pipeline-spaghetti-with-native-gitops&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let us look at a scenario that plays out weekly: rolling out a new microservice to dev, staging, and production.&lt;/p&gt;
&lt;p&gt;Historically, this meant writing manifests, setting up registries, fighting with GitHub Actions YAML to build and push images, configuring ArgoCD, and dealing with deploy key authentication. Scaling this to three clusters easily eats up &lt;strong&gt;8-12 hours&lt;/strong&gt; of engineering time.&lt;/p&gt;
&lt;p&gt;With Ankra, we collapse this toolchain:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Connect GitHub Once:&lt;/strong&gt; Authorize Ankra to access your repo. It automatically handles the GitOps engine and Stack Builder components.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;AI-Assisted Stack Generation:&lt;/strong&gt; Press &lt;code&gt;Cmd+J&lt;/code&gt; and describe your architecture (e.g., &lt;em&gt;“Create a backend deployment: 2 replicas, port 8080, /health check, 256Mi limit”&lt;/em&gt;). The AI generates context-aware manifests tailored to your cluster.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Deploy via Git:&lt;/strong&gt; Click deploy. Ankra commits the manifests to your repository. ArgoCD syncs them. Git remains your immutable source of truth.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Simplify App CI:&lt;/strong&gt; Your app’s GitHub Action now only does two things: builds the image and updates a single tag in the GitOps repo. Ankra handles the rest.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;All orchestration, dependency ordering, and rollback logic lives in Ankra’s engine, not in a fragile 300-line Bash script hidden inside a GitHub Action.&lt;/p&gt;
&lt;h2 id=&quot;the-edge-multiplier-one-click-stack-cloning&quot;&gt;The Edge Multiplier: One-Click Stack Cloning&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-edge-multiplier-one-click-stack-cloning&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A “Stack” in Ankra is a blueprint: your application, its database, ingress controllers, certificates, and monitoring, all mapped with explicit dependencies. Ankra knows the namespace must exist before the app, and the database must be ready before the service connects.&lt;/p&gt;
&lt;p&gt;Once you have a hardened production stack, scaling it to new edge sites is trivial:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Select “Clone to Cluster” on your hardened stack.&lt;/li&gt;
&lt;li&gt;Choose the target edge cluster.&lt;/li&gt;
&lt;li&gt;Click Clone.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Alternatively, for the CLI-driven workflow:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame is-terminal&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;&lt;/span&gt;&lt;span class=&quot;sr-only&quot;&gt;Terminal window&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;bash&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Clone a production stack to multiple edge sites instantly&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;site&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;in&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;warehouse-oslo&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;warehouse-helsinki&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;warehouse-copenhagen&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;; &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;do&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#61AFEF&quot;&gt;ankra&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;stacks&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;clone&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-stack&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;--to&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;$site&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#56B6C2&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt; &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;Cloned successfully to &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;$site&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;done&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;for site in warehouse-oslo warehouse-helsinki warehouse-copenhagen; do  ankra cluster stacks clone production-stack --to $site  echo &amp;quot;Cloned successfully to $site&amp;quot;done&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;handling-environment-variables-at-scale&quot;&gt;Handling Environment Variables at Scale&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#handling-environment-variables-at-scale&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Cloning only works if you can handle localized configurations. Ankra uses a cascading variable hierarchy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Organisation Variables:&lt;/strong&gt; Global defaults (e.g., base domain, registry URL).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Cluster Variables:&lt;/strong&gt; Site-specific overrides (e.g., storage classes, local subdomains).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stack Variables:&lt;/strong&gt; App-specific overrides (e.g., feature flags).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;When you clone &lt;code&gt;production-stack&lt;/code&gt; to &lt;code&gt;warehouse-oslo&lt;/code&gt;, it automatically inherits Oslo’s local variables. The template remains identical; the configuration localizes dynamically.&lt;/p&gt;
&lt;h2 id=&quot;ai-that-actually-understands-your-infrastructure&quot;&gt;AI That Actually Understands Your Infrastructure&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#ai-that-actually-understands-your-infrastructure&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most “AI for DevOps” tools are glorified documentation search engines. Ankra’s AI is fundamentally different because it has deterministic access to your real-time cluster state, deployment history, and dependency graphs.&lt;/p&gt;
&lt;p&gt;When an incident occurs, the AI performs &lt;strong&gt;Incident Triangulation&lt;/strong&gt;:&lt;/p&gt;

























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Telemetry Source&lt;/th&gt;&lt;th&gt;What the AI Analyzes&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Error Logs&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Pattern matches exceptions across the entire affected service chain.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Stack History&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Correlates incident timing with recent manifest or Helm value changes.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Resource Events&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Identifies OOMKills, scheduling failures, and CrashLoopBackOffs.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Dependencies&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;Traces failures through your service mesh and external integrations.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;p&gt;If you highlight a crashing pod and press &lt;code&gt;Cmd+J&lt;/code&gt;, the AI does not give you generic advice. It tells you: &lt;em&gt;“This pod is crash-looping because the latest Stack deployment lowered the memory limit to 256Mi, and your active connection pool requires 512Mi. I recommend reverting the last commit.”&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;At an edge site without an on-call SRE, this turns a two-hour outage into a five-minute fix.&lt;/p&gt;
&lt;h2 id=&quot;the-roi-collapsing-the-integration-tax&quot;&gt;The ROI: Collapsing the Integration Tax&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-roi-collapsing-the-integration-tax&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When your centralized dashboard, delivery system, GitOps engine, and observability stack are unified, the “integration tax” disappears. Here is the reality of managing 10 edge clusters:&lt;/p&gt;






























&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;Operational Task&lt;/th&gt;&lt;th&gt;The Legacy Approach&lt;/th&gt;&lt;th&gt;The Ankra Approach&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Import a new cluster&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;2-3 days (monitoring, RBAC, ArgoCD)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5 minutes&lt;/strong&gt; (one Helm command)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Set up CI/CD per cluster&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;4-6 hours (Actions + Argo + debug)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;30 minutes&lt;/strong&gt; (connect repo + clone)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Troubleshoot a failing pod&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;1-2 hours (kubectl + context switching)&lt;/td&gt;&lt;td&gt;&lt;strong&gt;5 minutes&lt;/strong&gt; (context-aware AI)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;strong&gt;Replicate stack to 10 sites&lt;/strong&gt;&lt;/td&gt;&lt;td&gt;2-3 weeks of engineering toil&lt;/td&gt;&lt;td&gt;&lt;strong&gt;One afternoon&lt;/strong&gt; (stack cloning)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h2 id=&quot;time-to-stop-building-plumbing&quot;&gt;Time to Stop Building Plumbing&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#time-to-stop-building-plumbing&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ankra is not replacing your cloud provider or your Kubernetes distribution. Whether you run EKS, K3s, vanilla Kubernetes, or bare-metal edge nodes, if it runs Kubernetes, Ankra manages it.&lt;/p&gt;
&lt;p&gt;If your team has grown past three clusters, you have likely realized that ad-hoc operational tooling does not scale. Your engineers should be building core product features, not writing bespoke CI/CD pipelines for every new warehouse or cell tower that comes online.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Your Git repo stays yours. Your Helm charts stay standard. Your Kubernetes remains untouched.&lt;/strong&gt; Ankra simply provides the management layer required to operate at scale.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Get started with Ankra today&lt;/a&gt; to see what a real single pane of glass looks like. Stop fighting your infrastructure, and start scaling it.&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Edge Computing</category><category>AI</category><category>CI/CD</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>AI Incident Management: From Alert to Resolution in Minutes</title><link>https://ankra.ai/blog/ai-incident-management</link><guid isPermaLink="true">https://ankra.ai/blog/ai-incident-management</guid><description>Stop drowning in alerts. Learn how Ankra&apos;s AI-powered incident management delivers root cause analysis and actionable fixes directly to Slack, reducing debugging time from hours to minutes.</description><pubDate>Sat, 17 Jan 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Your pod just crashed. Again. You get an alert in Slack that says “CrashLoopBackOff” and now you’re about to spend the next hour jumping between kubectl, logs, metrics dashboards, and recent deployments trying to figure out what went wrong. Sound familiar?&lt;/p&gt;
&lt;p&gt;Traditional alerting tells you something broke. It doesn’t tell you why, and it certainly doesn’t tell you how to fix it. That’s where Ankra’s AI incident management changes everything.&lt;/p&gt;
&lt;h2 id=&quot;the-problem-with-traditional-alerts&quot;&gt;The Problem with Traditional Alerts&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-problem-with-traditional-alerts&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most alerting systems are glorified notification pipelines. They detect a threshold breach, fire a webhook, and dump a message into Slack. Then it’s on you to:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;SSH into the cluster or set up kubectl context&lt;/li&gt;
&lt;li&gt;Find the failing pod and check its status&lt;/li&gt;
&lt;li&gt;Read through logs looking for errors&lt;/li&gt;
&lt;li&gt;Check recent deployments for changes&lt;/li&gt;
&lt;li&gt;Cross-reference with metrics to understand the timeline&lt;/li&gt;
&lt;li&gt;Search documentation or Stack Overflow for the error message&lt;/li&gt;
&lt;li&gt;Test a fix and hope it works&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;This process takes anywhere from 30 minutes to several hours. For critical production issues, that’s unacceptable.&lt;/p&gt;
&lt;h2 id=&quot;how-ankras-ai-changes-the-game&quot;&gt;How Ankra’s AI Changes the Game&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#how-ankras-ai-changes-the-game&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When an incident occurs in your Ankra-managed cluster, the AI doesn’t just notify you - it investigates for you. Because Ankra has access to your entire stack’s context, it can analyze the situation from multiple angles simultaneously.&lt;/p&gt;
&lt;h3 id=&quot;instant-root-cause-analysis&quot;&gt;Instant Root Cause Analysis&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#instant-root-cause-analysis&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The moment a pod enters a failure state, Ankra’s AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Pulls recent logs&lt;/strong&gt; from the failing container and related services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Analyzes Kubernetes events&lt;/strong&gt; for scheduling issues, resource constraints, or configuration problems&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reviews recent changes&lt;/strong&gt; to the stack, including Helm value updates, manifest changes, and addon upgrades&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Correlates with cluster metrics&lt;/strong&gt; to identify resource pressure or network issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traces dependencies&lt;/strong&gt; to find if the root cause is actually in an upstream service&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Within seconds, the AI synthesizes this information into a clear root cause analysis delivered directly to your Slack channel.&lt;/p&gt;
&lt;h3 id=&quot;actionable-slack-alerts&quot;&gt;Actionable Slack Alerts&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#actionable-slack-alerts&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Instead of a cryptic alert like:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;plaintext&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#abb2bf&quot;&gt;🚨 ALERT: Pod my-app-7d4f8b6c9-x2k4m is in CrashLoopBackOff&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;🚨 ALERT: Pod my-app-7d4f8b6c9-x2k4m is in CrashLoopBackOff&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;You get an intelligent incident report that reads like a post-mortem written by someone who actually understands your system:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;🔍 Incident Analysis: my-app CrashLoopBackOff&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Root Cause:&lt;/strong&gt; OOMKilled - Container exceeded memory limit&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Timeline:&lt;/strong&gt; At &lt;code&gt;14:32&lt;/code&gt; Helm values reduced memory from 512Mi to 256Mi. Rolling update at &lt;code&gt;14:33&lt;/code&gt;, pods at 78% memory by &lt;code&gt;14:34&lt;/code&gt;, OOM kill at &lt;code&gt;14:35&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Impact:&lt;/strong&gt; 2 of 3 replicas affected. Service degraded but not down.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Fix:&lt;/strong&gt; Increase memory limit to 512Mi or higher. Connection pool increased from 10→50 recently, which explains the failure.&lt;/p&gt;
&lt;p&gt;📎 &lt;strong&gt;View in Ankra&lt;/strong&gt; | 🔧 &lt;strong&gt;Apply Fix&lt;/strong&gt; | 📊 &lt;strong&gt;Full Analysis&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;No more guessing. The AI explains what happened, when it happened, and most importantly - how to fix it.&lt;/p&gt;
&lt;h2 id=&quot;deep-integration-with-ankras-debugging-tools&quot;&gt;Deep Integration with Ankra’s Debugging Tools&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#deep-integration-with-ankras-debugging-tools&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here’s where it gets powerful. Ankra’s AI isn’t just reading logs - it has access to every debugging tool in the platform:&lt;/p&gt;
&lt;h3 id=&quot;stack-context-awareness&quot;&gt;Stack Context Awareness&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#stack-context-awareness&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The AI understands your entire stack topology. When a database connection fails, it doesn’t just report the error. It knows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Which services depend on that database&lt;/li&gt;
&lt;li&gt;What credentials are configured&lt;/li&gt;
&lt;li&gt;Whether the database pod is healthy&lt;/li&gt;
&lt;li&gt;If there were recent network policy changes&lt;/li&gt;
&lt;li&gt;What the connection string looks like&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This context allows for precise diagnosis that would take a human engineer significant time to piece together.&lt;/p&gt;
&lt;h3 id=&quot;one-click-fixes&quot;&gt;One-Click Fixes&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#one-click-fixes&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For common issues, the AI can propose fixes that you can apply directly from Slack:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Memory/CPU adjustments&lt;/strong&gt; - Modify resource limits in your stack configuration&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rollback changes&lt;/strong&gt; - Revert to the last known working state&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Restart components&lt;/strong&gt; - Bounce specific pods or services&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Scale operations&lt;/strong&gt; - Increase replicas to handle load&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Click the “Apply Fix” button in Slack, and Ankra updates your stack configuration through the normal GitOps flow - with full audit trail and the ability to rollback.&lt;/p&gt;
&lt;h3 id=&quot;deep-dive-exploration&quot;&gt;Deep Dive Exploration&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#deep-dive-exploration&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When the fix isn’t obvious, the AI provides deep dive capabilities:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Live log streaming&lt;/strong&gt; with AI-highlighted anomalies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Resource visualization&lt;/strong&gt; showing CPU, memory, and network patterns&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency graph&lt;/strong&gt; highlighting affected components&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Event timeline&lt;/strong&gt; correlating changes across the stack&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Similar incidents&lt;/strong&gt; from your history with their resolutions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All accessible from a single link in the Slack message.&lt;/p&gt;
&lt;h2 id=&quot;real-world-impact&quot;&gt;Real-World Impact&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#real-world-impact&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Teams using Ankra’s AI incident management report dramatic improvements:&lt;/p&gt;
&lt;h3 id=&quot;before-ankra&quot;&gt;Before Ankra&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#before-ankra&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Mean Time to Detect (MTTD)&lt;/strong&gt;: Variable, often learned from users&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Mean Time to Resolution (MTTR)&lt;/strong&gt;: 45 minutes to several hours&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context switching&lt;/strong&gt;: Constant jumping between tools&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: “Ask the person who built it”&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;after-ankra&quot;&gt;After Ankra&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#after-ankra&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;MTTD&lt;/strong&gt;: Instant, proactive alerting&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;MTTR&lt;/strong&gt;: 5-10 minutes for common issues&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Context switching&lt;/strong&gt;: Everything in Slack + one platform&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Documentation&lt;/strong&gt;: AI explains the what, why, and how&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;One customer reduced their debugging time from an average of 2 hours to under 10 minutes for 80% of incidents. The AI handles the investigation while engineers focus on the remaining complex issues.&lt;/p&gt;
&lt;h2 id=&quot;setting-it-up&quot;&gt;Setting It Up&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#setting-it-up&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Getting started with AI incident management takes minutes:&lt;/p&gt;
&lt;h3 id=&quot;1-connect-slack&quot;&gt;1. Connect Slack&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#1-connect-slack&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;integrations&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;slack&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;webhook_url&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;https://hooks.slack.com/services/XXX/YYY/ZZZ&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;channel&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;#incidents&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;mention_on_critical&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;@oncall-team&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;integrations:  slack:    webhook_url: https://hooks.slack.com/services/XXX/YYY/ZZZ    channel: &amp;quot;#incidents&amp;quot;    mention_on_critical: &amp;quot;@oncall-team&amp;quot;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;2-configure-alert-rules&quot;&gt;2. Configure Alert Rules&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#2-configure-alert-rules&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Define what matters to your team:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;alerts&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;pod-failures&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;condition&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;pod.status == &amp;quot;CrashLoopBackOff&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;severity&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;critical&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ai_analysis&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;high-latency&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;condition&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;p99_latency &amp;gt; 500ms&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;severity&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;warning&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ai_analysis&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;alerts:  - name: pod-failures    condition: pod.status == &amp;quot;CrashLoopBackOff&amp;quot;    severity: critical    ai_analysis: true  - name: high-latency    condition: p99_latency &gt; 500ms    severity: warning    ai_analysis: true&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;3-enable-ai-analysis&quot;&gt;3. Enable AI Analysis&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#3-enable-ai-analysis&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;AI analysis is enabled by default for all alerts. The AI automatically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Gathers relevant context when an alert fires&lt;/li&gt;
&lt;li&gt;Performs root cause analysis&lt;/li&gt;
&lt;li&gt;Generates fix suggestions&lt;/li&gt;
&lt;li&gt;Sends enriched alerts to Slack&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;No configuration needed - it just works.&lt;/p&gt;
&lt;h2 id=&quot;privacy-and-security&quot;&gt;Privacy and Security&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#privacy-and-security&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your data stays yours. Ankra’s AI:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Runs analysis within your security boundary&lt;/li&gt;
&lt;li&gt;Never stores sensitive information externally&lt;/li&gt;
&lt;li&gt;Respects RBAC permissions in suggestions&lt;/li&gt;
&lt;li&gt;Logs all AI actions for audit compliance&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The AI only accesses what it needs for analysis and only suggests fixes you have permission to apply.&lt;/p&gt;
&lt;h2 id=&quot;beyond-reactive-proactive-insights&quot;&gt;Beyond Reactive: Proactive Insights&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#beyond-reactive-proactive-insights&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The AI doesn’t wait for things to break. It continuously monitors for:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resource trends&lt;/strong&gt; heading toward limits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configuration drift&lt;/strong&gt; from best practices&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dependency vulnerabilities&lt;/strong&gt; in your addons&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Capacity planning&lt;/strong&gt; alerts before you hit limits&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;You get warned about problems before they become incidents.&lt;/p&gt;
&lt;h2 id=&quot;the-future-of-incident-management&quot;&gt;The Future of Incident Management&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-future-of-incident-management&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The old model of alert → investigate → fix → document is being replaced by alert → understand → resolve. AI handles the investigation and documentation automatically. Engineers focus on decision-making and complex problem-solving.&lt;/p&gt;
&lt;p&gt;With Ankra, your Slack channel becomes a command center where incidents are understood and resolved, not just announced. Every alert comes with context. Every issue comes with a suggested path forward. Every resolution is documented and learned from.&lt;/p&gt;
&lt;p&gt;Stop spending hours debugging. Let the AI do the investigation while you focus on building.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;Ready to transform your incident management? &lt;a href=&quot;https://platform.ankra.app/auth/signup&quot;&gt;Get started with Ankra&lt;/a&gt; and experience AI-powered debugging in minutes, not hours.&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>AI</category><category>Observability</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Delivery that understands your stack</title><link>https://ankra.ai/blog/delivery-simplified-with-stacks</link><guid isPermaLink="true">https://ankra.ai/blog/delivery-simplified-with-stacks</guid><description>Traditional CI is fine. Delivery is where teams still bleed time. Learn how Ankra transforms delivery from a scripting problem to a graph problem, reducing pipeline build time from weeks to hours.</description><pubDate>Mon, 11 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The real slowdown in delivery isn’t one rebuild, it’s every change crawling through slow release cycles with messy dependencies. You can’t see other setups, Lifecycle is unclear, The code turns into technical debt fast. No one wants to touch it. You have to read too much before using it. Every tweak means rebuilding the same foundations across every pipeline. With Ankra, a few calls replace all that. With the Ankra Platform, your release cycles will be cut by up to 90 percent.&lt;/p&gt;
&lt;h2 id=&quot;what-ankra-does&quot;&gt;What Ankra does&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-ankra-does&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Ankra treats delivery as a graph problem, not a scripting problem. The moment a resource enters the system, it gets a lifecycle. We keep a strict DAG of dependencies and update only what changed, in the right order, and in parallel where it is safe. Validation and readiness live with the resources, not in scattered scripts. Because the engine knows order and health, you are not writing custom waits and retries. In practice, the hand written job count falls sharply.&lt;/p&gt;
&lt;h2 id=&quot;ai-assistant-in-the-platform&quot;&gt;AI Assistant in the platform&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#ai-assistant-in-the-platform&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The AI assistant helps DevOps design stacks with clear guardrails and immediate feedback on order, health, and impact. Developers can see what the platform team configured, understand why, and resolve customizations or small fixes themselves without waiting on DevOps. Technical managers and security officers, validate posture and policy, compare environments, and understand lifecycle timing without extra permissions. The AI assistant explains dependencies and requirements in plain language and links back to the nodes in the graph. All in one platform.&lt;/p&gt;
&lt;h2 id=&quot;how-it-fits-your-workflow&quot;&gt;How it fits your workflow&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#how-it-fits-your-workflow&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Most teams keep their current tools and change the shape of the work.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Package the app with Docker and Helm, push to your registry and repo.&lt;/li&gt;
&lt;li&gt;Connect your Git repository and credentials so the engine can write back.&lt;/li&gt;
&lt;li&gt;Import the Helm chart into Stack Builder and map dependencies like DB, cache, ingress, and observability.&lt;/li&gt;
&lt;li&gt;Preview the plan, then deploy. The engine runs the lifecycle and commits results to Git.&lt;/li&gt;
&lt;li&gt;Operate through Git, Terraform, CLI, or API as needed. Same engine, same rules.&lt;/li&gt;
&lt;li&gt;Spin up a new environment by copying the stack folder, adjusting inputs, and committing. Minutes, not days.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/stack-builder.webp&quot; alt=&quot;Stack Builder Interface - Visual dependency mapping and stack configuration&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;h2 id=&quot;impact-in-practice&quot;&gt;Impact in practice&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#impact-in-practice&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In customer and users work, we see large drops in effort and lead time because the engine absorbs the choreography and runs only what is needed. Pipeline builds shrink because order, waits, and checks come from the graph instead of hand written jobs. Teams report fewer blocked by DevOps, as developers import Helm, assemble stacks, preview plans, and deploy without waiting on DevOps approval or TicketOps. Convergence is faster because only changes are isolated and safe paths run in parallel. When a provider cannot do partial updates, the engine narrows the blast radius so unrelated resources do not restart. Developers can become capable to solve problems and configurations themselves, while managers and security validate live setups without cluster credentials.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Fewer deliver blockers, more time on product work.&lt;/li&gt;
&lt;li&gt;Faster path from idea to merge to running service.&lt;/li&gt;
&lt;li&gt;Fewer rollbacks and narrower incidents, which lowers the cost of change.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;next-generation-optimization&quot;&gt;Next-generation optimization&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#next-generation-optimization&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Changing configs in Kubernetes shouldn’t be a slow, painful process. With live feedback, instant edits, and context-aware assistance, you can tweak settings and see the results in the dependency graph immediately. No waiting on long deploy cycles just make the change, watch it update, and keep moving. It s built for speed, for experimenting, and for getting deployments exactly right without the guesswork. This is DevOps in real time. Fine tune in the fastest way possible, roll out when its ready, all from one platform.&lt;/p&gt;
&lt;h2 id=&quot;git-as-the-source-of-truth&quot;&gt;Git as the source of truth&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#git-as-the-source-of-truth&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Every action the engine takes is written to your repository. You get history, diffs, pull request reviews, and rollbacks without inventing conventions. It is clean for machine to machine automation: systems can read one repo, produce signed commits, open pull requests, and let policy engines approve or reject based on code and context. You see who changed what, when, and why, and you can link each change to tickets and releases. Collaboration improves because product, security, and operations share the same record. Reviews speed up, audits take hours instead of days, and incident timelines are easier to reconstruct. UI and Git stay aligned. If you click in the UI, the engine still writes to Git. If you commit in Git, the engine reconciles the same way. One system. One truth.&lt;/p&gt;
&lt;p&gt;A minimal, single manifest and single addon example. Simple, readable, and ready to drop in.&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ImportCluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;imported-cluster&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Simple example with one manifest and one addon&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;git_repository&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;provider&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;github&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;credential_name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;github credential id&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;branch&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;main&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;repository&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;username&amp;gt;/&amp;lt;gitops repository&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;stacks&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;monitoring&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;manifests&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana-ns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from_file&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;manifests/grafana-ns.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;addons&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;chart_name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;chart_version&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;9.2.10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;repository_url&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;https://grafana.github.io/helm-charts&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;namespace&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;configuration_type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;standalone&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;configuration&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from_file&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;add-ons/grafana/values.yaml&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;parents&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;grafana-ns&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;manifest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: v1kind: ImportClustermetadata:  name: imported-cluster  description: Simple example with one manifest and one addonspec:  git_repository:    provider: github    credential_name: &lt;github credential id&gt;    branch: &lt;main&gt;    repository: &lt;username&gt;/&lt;gitops repository&gt;  stacks:  - name: monitoring    manifests:    - name: grafana-ns      from_file: manifests/grafana-ns.yaml    addons:    - name: grafana      chart_name: grafana      chart_version: 9.2.10      repository_url: https://grafana.github.io/helm-charts      namespace: grafana      configuration_type: standalone      configuration:        from_file: add-ons/grafana/values.yaml      parents:      - name: grafana-ns        kind: manifest&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;what-this-replaces&quot;&gt;What this replaces&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-this-replaces&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you have maintained delivery YAML, you know the bloat. Wait loops because readiness is hard to observe. Custom sequencing because dependency order is implicit. Duplicate validation because the job runner cannot see your resources. Retries without context. Ankra absorbs that work. Health and readiness are native. Order comes from the graph. Validations run where the resource lives. Retries happen with context. The day to day effect is fewer moving parts to babysit and more time spent on product work.&lt;/p&gt;
&lt;h2 id=&quot;repeatability-and-safety&quot;&gt;Repeatability and safety&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#repeatability-and-safety&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Build an environment once and it’s easy to clone it, evolve it, or retire it cleanly. Because the plan is derived from the same DAG every time, you get deterministic outcomes from the same inputs. That holds in the UI, a commit, Terraform, the CLI, or an API call. The surface area for error shrinks, rollbacks are clean, and change failure rate trends down as you replace ad hoc scripts with a system that understands dependencies.&lt;/p&gt;
&lt;h2 id=&quot;the-backbone&quot;&gt;The backbone&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-backbone&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A strict DAG gives safe parallelism, predictable sequencing, and clear failure domains. It also lets us decide what not to touch while still landing your change. That restraint is where much of the speed up comes from. Fewer components restarted. Fewer paths for things to go sideways. Less rework after the fact.&lt;/p&gt;</content:encoded><dc:creator>Mark Shine</dc:creator><category>Stacks</category><category>CI/CD</category><category>GitOps</category><category>Kubernetes</category><category>DevOps</category></item><item><title>The Minimalist’s Guide to Homelab Setup</title><link>https://ankra.ai/blog/minimalist-guide</link><guid isPermaLink="true">https://ankra.ai/blog/minimalist-guide</guid><description>Deploy your favourite and essential homelab applications with Ankra in just a few clicks</description><pubDate>Mon, 11 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Welcome wanderer!&lt;/p&gt;
&lt;p&gt;If you’ve clicked on this blog, you either stumbled upon Ankra and are finding out how it can accelerate your productivity, or are just curious about building homelab in simple steps.&lt;/p&gt;
&lt;p&gt;By the end of this guide, you will have a WordPress blog hosted on your homelab, accessible securely from anywhere via a Cloudflare tunnel.&lt;/p&gt;
&lt;p&gt;Before we dive right into it, here are the &lt;em&gt;recommended&lt;/em&gt; prerequisites to go ahead. In case you don’t meet the requirements, don’t worry, we got you covered.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ankra account: head out to &lt;a href=&quot;https://ankra.ai&quot;&gt;ankra.ai&lt;/a&gt; to create one if you already don’t have one&lt;/li&gt;
&lt;li&gt;A Kubernetes Cluster: It does not have to be on a cloud provider. You can have a small single node cluster with &lt;a href=&quot;https://kind.sigs.k8s.io/&quot;&gt;kind&lt;/a&gt; or &lt;a href=&quot;https://minikube.sigs.k8s.io/docs/start/?arch=%2Fmacos%2Farm64%2Fstable%2Fbinary+download&quot;&gt;minikube&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;A domain of your choice: This is so that all your applications can have a subdomain of your choice. A domain on &lt;a href=&quot;https://www.cloudflare.com/en-gb/&quot;&gt;cloudflare&lt;/a&gt; or &lt;a href=&quot;http://godaddy.com&quot;&gt;godaddy&lt;/a&gt; can help you access your homelab applications from anywhere in the world. If not, you can have a domain locally in your home network.&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id=&quot;setting-up-your-cluster&quot;&gt;Setting up your cluster&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#setting-up-your-cluster&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now that we have out prerequisites covered, let’s start with setting everything up.&lt;/p&gt;
&lt;p&gt;Upon creating an Ankra account, you shall be prompted to import a Kubernetes cluster, follow along.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/import-cluster.webp&quot; alt=&quot;Landing Page&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Once you give it a name and click on import, you get a pop up to install Ankra agent on your cluster.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/helm-command.webp&quot; alt=&quot;Helm command&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;If you forgot to copy the command, you can always go to settings and click on generate command like below.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/regenerate-helm-command.webp&quot; alt=&quot;Helm command&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;You should see this if the command has run successfully&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/cluster-reconciled.png&quot; alt=&quot;Reconciled successfully&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Now that we have connected our cluster, it’s time to deploy some stacks.&lt;/p&gt;
&lt;p&gt;To begin with, we need to connect a github account/repository so that a backend IAAC can be configured. Click on stacks on the left pane&lt;/p&gt;
&lt;h2 id=&quot;setting-up-iaac&quot;&gt;Setting up IAAC&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#setting-up-iaac&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/default-stack.webp&quot; alt=&quot;Default Stack Page&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/github-connect.webp&quot; alt=&quot;Connect to GitHub&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Once this is done, any applications you add/update/delete on the UI will reflect on your repository and vice-versa.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;It’s important to know that all kubernetes manifests will automatically be committed to the git repository you connect Ankra with. Make sure you do not commit any secrets/api keys to a public repository.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;I have a cloudflare domain &lt;a href=&quot;http://shivu.io&quot;&gt;shivu.io&lt;/a&gt; and I want to deploy a wordpress app on the homelab. Wordpress can be used for various things. I want to have a handy workspace for all my blog ideas and it’s a great tool for that purpose.&lt;/p&gt;
&lt;p&gt;Once the stack is deployed, I will have a &lt;a href=&quot;http://wordpress.shivu.io&quot;&gt;wordpress.shivu.io&lt;/a&gt; deployed with ssl enabled, so the website will be https and I can access it from anywhere on the internet.&lt;/p&gt;
&lt;h2 id=&quot;deploying-your-stack&quot;&gt;Deploying your stack&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#deploying-your-stack&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A stack on Ankra is a set of applications logically put together in the form of a interactive flowchart. Ankra supports applications as Addons (helm charts) or Manifests. For my stack, I will have the following applications.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://artifacthub.io/packages/helm/bitnami/wordpress&quot;&gt;Wordpress&lt;/a&gt;: Community helm chart as an Addon&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://artifacthub.io/packages/helm/cert-manager/cert-manager&quot;&gt;Cert Manager&lt;/a&gt;: Community helm chart as an Addon for certificates
&lt;ul&gt;
&lt;li&gt;ClusterIssuer: A single manifest additional to the add on to specify cloudflare as my domain issuer.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://community-charts.github.io/docs/category/cloudflared&quot;&gt;Cloudflared&lt;/a&gt;: Community helm chart as an Addon for tunnelling locally hosted applications to the internet.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/stack-builder.webp&quot; alt=&quot;Ankra Stack&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The values.yaml for all these are as below&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;wordpress-values.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Global parameters&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;global&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;imageRegistry&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;imagePullSecrets&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;defaultStorageClass&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;standard&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;security&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;allowInsecureImages&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Common configuration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kubeVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;nameOverride&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;fullnameOverride&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;commonLabels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;commonAnnotations&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;clusterDomain&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cluster.local&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;extraDeploy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;usePasswordFiles&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;diagnosticMode&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# WordPress Image&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;registry&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;docker.io&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;repository&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bitnami/wordpress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;tag&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;digest&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pullPolicy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;IfNotPresent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pullSecrets&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;debug&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# WordPress Configuration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;wordpressUsername&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;admin&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;wordpressPassword&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;devpassword123&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;wordpressEmail&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;dev@example.com&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;wordpressBlogName&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Dev Blog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;persistence&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;storageClass&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;accessModes&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ReadWriteOnce&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;2Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Deployment Settings&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;replicaCount&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;updateStrategy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;RollingUpdate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;schedulerName&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;terminationGracePeriodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;topologySpreadConstraints&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;priorityClassName&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;automountServiceAccountToken&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Resource Allocation&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;resourcesPreset&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;nano&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;resources&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;requests&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;100m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;128Mi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;limits&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;250m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;256Mi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Service Configuration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;service&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;wordpress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ClusterIP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;http&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;https&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;443&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;clusterIP&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;loadBalancerIP&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;loadBalancerSourceRanges&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: []&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Database Configuration&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;mariadb&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;architecture&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;standalone&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;auth&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;rootPassword&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;rootpassword&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;database&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bitnami_wordpress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;username&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;bn_wordpress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;password&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;dbpassword&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;primary&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;persistence&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;storageClass&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;accessModes&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ReadWriteOnce&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;size&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;2Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Disable Production Features&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;autoscaling&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pdb&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;create&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metrics&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;networkPolicy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;memcached&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;enabled&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Development-Specific Overrides&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;allowEmptyPassword&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;wordpressSkipInstall&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;overrideDatabaseSettings&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;# Global parametersglobal:  imageRegistry: &amp;quot;&amp;quot;  imagePullSecrets: []  defaultStorageClass: &amp;quot;standard&amp;quot;  security:    allowInsecureImages: true# Common configurationkubeVersion: &amp;quot;&amp;quot;nameOverride: &amp;quot;&amp;quot;fullnameOverride: &amp;quot;&amp;quot;commonLabels: {}commonAnnotations: {}clusterDomain: cluster.localextraDeploy: []usePasswordFiles: truediagnosticMode:  enabled: false# WordPress Imageimage:  registry: docker.io  repository: bitnami/wordpress  tag: latest  digest: &amp;quot;&amp;quot;  pullPolicy: IfNotPresent  pullSecrets: []  debug: true# WordPress ConfigurationwordpressUsername: adminwordpressPassword: devpassword123wordpressEmail: dev@example.comwordpressBlogName: Dev Blogpersistence:  enabled: true  storageClass: &amp;quot;&amp;quot;  accessModes:    - ReadWriteOnce  size: 2Gi# Deployment SettingsreplicaCount: 1updateStrategy:  type: RollingUpdateschedulerName: &amp;quot;&amp;quot;terminationGracePeriodSeconds: &amp;quot;&amp;quot;topologySpreadConstraints: []priorityClassName: &amp;quot;&amp;quot;automountServiceAccountToken: false# Resource AllocationresourcesPreset: &amp;quot;nano&amp;quot;resources:  requests:    cpu: 100m    memory: 128Mi  limits:    cpu: 250m    memory: 256Mi# Service Configurationservice:  metadata:    name: wordpress  type: ClusterIP  ports:    http: 80    https: 443  clusterIP: &amp;quot;&amp;quot;  loadBalancerIP: &amp;quot;&amp;quot;  loadBalancerSourceRanges: []# Database Configurationmariadb:  enabled: true  architecture: standalone  auth:    rootPassword: rootpassword    database: bitnami_wordpress    username: bn_wordpress    password: dbpassword  primary:    persistence:      enabled: true      storageClass: &amp;quot;&amp;quot;      accessModes:        - ReadWriteOnce      size: 2Gi# Disable Production Featuresautoscaling:  enabled: falsepdb:  create: falsemetrics:  enabled: falsenetworkPolicy:  enabled: falsememcached:  enabled: false# Development-Specific OverridesallowEmptyPassword: truewordpressSkipInstall: falseoverrideDatabaseSettings: true&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;To ensure WordPress runs smoothly without crashing or timing out, it’s crucial to configure resource limits and requests in your Helm chart values. For example, setting modest CPU and memory limits helps Kubernetes manage pod stability and readiness checks effectively.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;One additional thing that cert-manager requires is the cloudflare api token to create certs for the domains configured.&lt;/p&gt;
&lt;p&gt;You can create this by executing:&lt;/p&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;kubectl -n cert-manager create secret generic cloudflare-api-token-secret --from-literal=api-token=&amp;lt;YOUR_CLOUDFLARE_API_TOKEN&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;kubectl -n cert-manager create secret generic cloudflare-api-token-secret --from-literal=api-token=&lt;YOUR_CLOUDFLARE_API_TOKEN&gt;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;cert-manager-values.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;installCRDs&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;installCRDs: true&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;clusterissuer-manifest.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cert-manager.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ClusterIssuer&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;letsencrypt-dns01&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;acme&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;email&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;lt;your-email&amp;gt;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;privateKeySecretRef&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;letsencrypt-dns01&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;server&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;https://acme-v02.api.letsencrypt.org/directory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;solvers&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;dns01&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cloudflare&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiTokenSecretRef&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;key&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;api-token&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cloudflare-api-token&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: cert-manager.io/v1kind: ClusterIssuermetadata:  name: letsencrypt-dns01spec:  acme:    email: &lt;your-email&gt;    privateKeySecretRef:      name: letsencrypt-dns01    server: https://acme-v02.api.letsencrypt.org/directory    solvers:    - dns01:        cloudflare:          apiTokenSecretRef:            key: api-token            name: cloudflare-api-token&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;In order to configure cloudflared tunnel, you need a couple of things. In order to generate them. Install &lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/downloads/&quot;&gt;cloudflared&lt;/a&gt; locally. Setting this up might take a while if you are new to cloudflare, but the docs are clear and concise.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/tutorials/cli/&quot;&gt;Pem certificate&lt;/a&gt;: Upon login, a pem file is generated.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://developers.cloudflare.com/cloudflare-one/connections/connect-networks/do-more-with-tunnels/local-management/tunnel-useful-commands/&quot;&gt;Config File&lt;/a&gt;: Upon creation of a tunnel, a config is placed in ~/.cloudflared/config&lt;/li&gt;
&lt;/ol&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;cloudflared-values.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;tunnelSecrets&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;base64EncodedPemFile&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;lt;base64 encoded pem file&amp;gt;&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;base64EncodedConfigJsonFile&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;&amp;lt;base64 encoded config.json&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;replica&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# -- This will use DaemonSet to deploy cloudflared to all nodes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;allNodes&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# -- If previous flag disabled, this will use Deployment to deploy cloudflared only number of following count&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;count&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;tunnelConfig&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cloudflared-tunnel&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metricsUpdateFrequency&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;10s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;logLevel&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;info&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;warpRouting&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ingress&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;hostname&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;wordpress.shivu.io&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;service&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;http://wordpress.wordpress.svc.cluster.local:80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;service&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;http_status:404&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;tunnelSecrets:  base64EncodedPemFile: &amp;quot;&lt;base64 encoded pem file&gt;&amp;quot;  base64EncodedConfigJsonFile: &amp;quot;&lt;base64 encoded config.json&amp;quot;replica:  # -- This will use DaemonSet to deploy cloudflared to all nodes  allNodes: false  # -- If previous flag disabled, this will use Deployment to deploy cloudflared only number of following count  count: 1tunnelConfig:  name: cloudflared-tunnel  metricsUpdateFrequency: 10s  logLevel: info  warpRouting: trueingress:  - hostname: wordpress.shivu.io    service: http://wordpress.wordpress.svc.cluster.local:80  - service: http_status:404&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;Click on apply on the bottom of the page and you’re good to go.&lt;/p&gt;
&lt;p&gt;In order to access your wordpress on the browser, you must add the URL of your tunnel as a CNAME record on the cloudflare dashboard.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/cloudflare-dns-record.webp&quot; alt=&quot;Cloudflare Dashboard&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;The target here is &lt;code&gt;&amp;lt;tunnel-id&amp;gt;.cfargotunnel.com&lt;/code&gt;. The tunnel-id can be fetched from the cloudflare dashboard or the first line of the cloudflared logs.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/cloudflared-logs.webp&quot; alt=&quot;Cloudflared Logs&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;A quick clarification: The Cloudflared tunnel works independently from Kubernetes ingress controllers. While Kubernetes ingress manages traffic routing inside your cluster, the Cloudflared tunnel securely connects traffic from Cloudflare’s network to your cluster. Think of Cloudflared as the gateway that tunnels external requests safely, whereas Kubernetes ingress handles traffic once inside the cluster.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;accessing-your-application&quot;&gt;Accessing your application&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#accessing-your-application&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If everything goes well, you should see this on your hostname&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;/images/blog-minimalist-guide/wordpress-landing-page.webp&quot; alt=&quot;Wordpress Screenshot&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot;/&gt;&lt;/p&gt;
&lt;p&gt;Common points to debug:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check the logs of cert-manager if it has created the necessary certificates&lt;/li&gt;
&lt;li&gt;Check the logs of cloudflared pods if it has registered the tunnel&lt;/li&gt;
&lt;li&gt;Check the wordpress logs if it is serving traffic&lt;/li&gt;
&lt;li&gt;Check the initial cloudflared values.yaml to make sure you’ve provided the right names for the service, hostname and namespace.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Join our slack: &lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;&lt;strong&gt;Join Community&lt;/strong&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Follow us on: &lt;a href=&quot;https://www.linkedin.com/company/ankra&quot;&gt;LinkedIn&lt;/a&gt;, &lt;a href=&quot;https://github.com/ankraio&quot;&gt;GitHub&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Contact us: &lt;a href=&quot;mailto:hello@ankra.ai&quot;&gt;hello@ankra.ai&lt;/a&gt;&lt;/p&gt;</content:encoded><dc:creator>Shiva Swaroop N K</dc:creator><category>Homelab</category><category>Kubernetes</category><category>DevOps</category></item><item><title>Kubernetes Best Practices for Production Deployments</title><link>https://ankra.ai/blog/kubernetes-best-practices</link><guid isPermaLink="true">https://ankra.ai/blog/kubernetes-best-practices</guid><description>Master the essential strategies and patterns for running reliable, scalable applications on Kubernetes in production. Learn from real-world examples and avoid common pitfalls.</description><pubDate>Wed, 06 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Running applications in production on Kubernetes is challenging, but following proven best practices can make the difference between a reliable system and a maintenance nightmare. This guide covers the essential strategies that successful teams use to deploy and maintain production workloads.&lt;/p&gt;
&lt;h2 id=&quot;what-youll-learn&quot;&gt;What You’ll Learn&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#what-youll-learn&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;By the end of this guide, you’ll understand:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;How to design resilient deployments that handle failures gracefully&lt;/li&gt;
&lt;li&gt;Security practices that protect your applications from common threats&lt;/li&gt;
&lt;li&gt;Monitoring strategies that give you visibility into your system’s health&lt;/li&gt;
&lt;li&gt;Scaling patterns that keep your applications performant under load&lt;/li&gt;
&lt;li&gt;Backup and recovery procedures that protect your data&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;1-resource-management-the-foundation-of-stability&quot;&gt;1. Resource Management: The Foundation of Stability&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#1-resource-management-the-foundation-of-stability&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;why-resource-management-matters&quot;&gt;Why Resource Management Matters&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#why-resource-management-matters&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Resource management is the cornerstone of stable Kubernetes deployments. Without proper resource allocation, your applications can experience:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Resource starvation&lt;/strong&gt; when one pod consumes all available CPU/memory&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;OOM kills&lt;/strong&gt; when containers exceed memory limits&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Poor performance&lt;/strong&gt; due to CPU throttling&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unpredictable scaling&lt;/strong&gt; behavior&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;best-practice-always-set-resource-limits&quot;&gt;Best Practice: Always Set Resource Limits&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#best-practice-always-set-resource-limits&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;link rel=&quot;stylesheet&quot; href=&quot;/_astro/ec.darku.css&quot;/&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;resources.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;replicas&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;selector&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;matchLabels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;labels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;containers&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app:v1.2.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;resources&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;requests&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;512Mi&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;250m&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;limits&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;1Gi&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;500m&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;livenessProbe&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;httpGet&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/health&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;initialDelaySeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;30&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;periodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;timeoutSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;failureThreshold&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;readinessProbe&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;httpGet&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/ready&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;initialDelaySeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;periodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;timeoutSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;failureThreshold&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: apps/v1kind: Deploymentmetadata:  name: production-appspec:  replicas: 3  selector:    matchLabels:      app: production-app  template:    metadata:      labels:        app: production-app    spec:      containers:      - name: app        image: production-app:v1.2.0        resources:          requests:            memory: &amp;quot;512Mi&amp;quot;            cpu: &amp;quot;250m&amp;quot;          limits:            memory: &amp;quot;1Gi&amp;quot;            cpu: &amp;quot;500m&amp;quot;        livenessProbe:          httpGet:            path: /health            port: 8080          initialDelaySeconds: 30          periodSeconds: 10          timeoutSeconds: 5          failureThreshold: 3        readinessProbe:          httpGet:            path: /ready            port: 8080          initialDelaySeconds: 5          periodSeconds: 5          timeoutSeconds: 3          failureThreshold: 3&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Key Points:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Requests&lt;/strong&gt;: Guaranteed resources your pod will receive&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Limits&lt;/strong&gt;: Maximum resources your pod can use&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Health Checks&lt;/strong&gt;: Essential for Kubernetes to know when pods are healthy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Realistic Values&lt;/strong&gt;: Base limits on actual usage patterns, not guesses&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;pro-tip-use-resource-quotas&quot;&gt;Pro Tip: Use Resource Quotas&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#pro-tip-use-resource-quotas&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;resource-quota.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ResourceQuota&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-quota&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;hard&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;requests.cpu&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;4&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;requests.memory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;8Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;limits.cpu&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;8&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;limits.memory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;16Gi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;pods&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;20&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: v1kind: ResourceQuotametadata:  name: production-quotaspec:  hard:    requests.cpu: &amp;quot;4&amp;quot;    requests.memory: 8Gi    limits.cpu: &amp;quot;8&amp;quot;    limits.memory: 16Gi    pods: &amp;quot;20&amp;quot;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;2-security-protect-your-applications&quot;&gt;2. Security: Protect Your Applications&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#2-security-protect-your-applications&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;the-security-first-approach&quot;&gt;The Security-First Approach&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-security-first-approach&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Security in Kubernetes requires careful attention. The principle of least privilege should guide every security decision.&lt;/p&gt;
&lt;h3 id=&quot;best-practice-run-as-non-root&quot;&gt;Best Practice: Run as Non-Root&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#best-practice-run-as-non-root&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;run-as-non-root.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;secure-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;securityContext&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;runAsNonRoot&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;runAsUser&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;1000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;fsGroup&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;2000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;containers&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;secure-app:latest&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;securityContext&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;allowPrivilegeEscalation&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;false&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;readOnlyRootFilesystem&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;capabilities&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;drop&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ALL&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;volumeMounts&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;tmp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;mountPath&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/tmp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;varlog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;mountPath&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/var/log&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;mountPath&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/app/config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;readOnly&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;volumes&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;tmp&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;emptyDir&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;varlog&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;emptyDir&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: {}&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;configMap&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: apps/v1kind: Deploymentmetadata:  name: secure-appspec:  template:    spec:      securityContext:        runAsNonRoot: true        runAsUser: 1000        fsGroup: 2000      containers:      - name: app        image: secure-app:latest        securityContext:          allowPrivilegeEscalation: false          readOnlyRootFilesystem: true          capabilities:            drop:            - ALL        volumeMounts:        - name: tmp          mountPath: /tmp        - name: varlog          mountPath: /var/log        - name: app-config          mountPath: /app/config          readOnly: true      volumes:      - name: tmp        emptyDir: {}      - name: varlog        emptyDir: {}      - name: app-config        configMap:          name: app-config&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Security Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Non-root execution&lt;/strong&gt; prevents privilege escalation attacks&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Read-only filesystem&lt;/strong&gt; prevents malicious file modifications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Dropped capabilities&lt;/strong&gt; remove unnecessary privileges&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;ConfigMap mounting&lt;/strong&gt; keeps configuration separate and secure&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;pro-tip-use-network-policies&quot;&gt;Pro Tip: Use Network Policies&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#pro-tip-use-network-policies&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;network-policy.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;networking.k8s.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;NetworkPolicy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app-network-policy&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;podSelector&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;matchLabels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;app&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;policyTypes&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Ingress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Egress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ingress&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;from&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;namespaceSelector&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;matchLabels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;frontend&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;protocol&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;TCP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;egress&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;to&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;namespaceSelector&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;matchLabels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;database&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ports&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;protocol&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;TCP&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5432&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: networking.k8s.io/v1kind: NetworkPolicymetadata:  name: app-network-policyspec:  podSelector:    matchLabels:      app: production-app  policyTypes:  - Ingress  - Egress  ingress:  - from:    - namespaceSelector:        matchLabels:          name: frontend    ports:    - protocol: TCP      port: 8080  egress:  - to:    - namespaceSelector:        matchLabels:          name: database    ports:    - protocol: TCP      port: 5432&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;3-monitoring-and-observability-know-your-system&quot;&gt;3. Monitoring and Observability: Know Your System&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#3-monitoring-and-observability-know-your-system&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;the-three-pillars-of-observability&quot;&gt;The Three Pillars of Observability&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-three-pillars-of-observability&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Metrics&lt;/strong&gt;: Quantitative data about your system’s performance&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Logs&lt;/strong&gt;: Detailed records of events and errors&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Traces&lt;/strong&gt;: Request flow through your distributed system&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;best-practice-comprehensive-monitoring-setup&quot;&gt;Best Practice: Comprehensive Monitoring Setup&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#best-practice-comprehensive-monitoring-setup&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;prometheus-config.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;ConfigMap&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;prometheus-config&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;data&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;prometheus.yml&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#CD89E1&quot;&gt;|&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;global:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;scrape_interval: 15s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;evaluation_interval: 15s&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;rule_files:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;- &amp;quot;alert_rules.yml&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;scrape_configs:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;- job_name: &amp;#39;kubernetes-pods&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;kubernetes_sd_configs:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;- role: pod&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;relabel_configs:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;action: keep&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;regex: true&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;action: replace&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;target_label: __metrics_path__&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;regex: (.+)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;action: replace&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;regex: ([^:]+)(?::\d+)?;(\d+)&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;replacement: $1:$2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;        &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;target_label: __address__&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: v1kind: ConfigMapmetadata:  name: prometheus-configdata:  prometheus.yml: |    global:      scrape_interval: 15s      evaluation_interval: 15s    rule_files:      - &amp;quot;alert_rules.yml&amp;quot;    scrape_configs:    - job_name: &apos;kubernetes-pods&apos;      kubernetes_sd_configs:      - role: pod      relabel_configs:      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]        action: keep        regex: true      - source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]        action: replace        target_label: __metrics_path__        regex: (.+)      - source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]        action: replace        regex: ([^:]+)(?::\d+)?;(\d+)        replacement: $1:$2        target_label: __address__&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;essential-metrics-to-monitor&quot;&gt;Essential Metrics to Monitor&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#essential-metrics-to-monitor&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;alert-rules.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Example alerting rules&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;groups&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;kubernetes.rules&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;rules&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;HighCPUUsage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;expr&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;container_cpu_usage_seconds_total{container!=&amp;quot;&amp;quot;} &amp;gt; 0.8&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;5m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;labels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;severity&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;warning&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;annotations&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;High CPU usage detected&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;Container {{ $labels.container }} is using {{ $value }} CPU&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;
&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;alert&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;HighMemoryUsage&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;expr&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;container_memory_usage_bytes{container!=&amp;quot;&amp;quot;} / container_spec_memory_limit_bytes{container!=&amp;quot;&amp;quot;} &amp;gt; 0.85&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;5m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;labels&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;severity&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;warning&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;annotations&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;summary&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;High memory usage detected&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;description&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;Container {{ $labels.container }} is using {{ $value | humanizePercentage }} memory&amp;quot;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;# Example alerting rulesgroups:- name: kubernetes.rules  rules:  - alert: HighCPUUsage    expr: container_cpu_usage_seconds_total{container!=&amp;quot;&amp;quot;} &gt; 0.8    for: 5m    labels:      severity: warning    annotations:      summary: &amp;quot;High CPU usage detected&amp;quot;      description: &amp;quot;Container {{ $labels.container }} is using {{ $value }} CPU&amp;quot;  - alert: HighMemoryUsage    expr: container_memory_usage_bytes{container!=&amp;quot;&amp;quot;} / container_spec_memory_limit_bytes{container!=&amp;quot;&amp;quot;} &gt; 0.85    for: 5m    labels:      severity: warning    annotations:      summary: &amp;quot;High memory usage detected&amp;quot;      description: &amp;quot;Container {{ $labels.container }} is using {{ $value | humanizePercentage }} memory&amp;quot;&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;4-scaling-strategies-handle-traffic-spikes&quot;&gt;4. Scaling Strategies: Handle Traffic Spikes&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#4-scaling-strategies-handle-traffic-spikes&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;horizontal-vs-vertical-scaling&quot;&gt;Horizontal vs Vertical Scaling&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#horizontal-vs-vertical-scaling&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;strong&gt;Horizontal scaling&lt;/strong&gt; (adding more pods) is generally preferred in Kubernetes because it’s more resilient and can handle traffic spikes better.&lt;/p&gt;
&lt;h3 id=&quot;best-practice-implement-hpa-with-multiple-metrics&quot;&gt;Best Practice: Implement HPA with Multiple Metrics&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#best-practice-implement-hpa-with-multiple-metrics&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;hpa-config.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;autoscaling/v2&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;HorizontalPodAutoscaler&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app-hpa&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;scaleTargetRef&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;minReplicas&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;maxReplicas&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;20&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metrics&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Resource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;cpu&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Utilization&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;averageUtilization&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;70&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Resource&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;resource&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;memory&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Utilization&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;averageUtilization&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;80&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Object&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;object&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metric&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;requests-per-second&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;describedObject&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;networking.k8s.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Ingress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app-ingress&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;target&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Value&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;1000&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;behavior&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;scaleDown&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;300&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;policies&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Percent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;periodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;60&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;scaleUp&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;stabilizationWindowSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;60&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;policies&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Percent&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;value&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;100&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;periodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;15&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: autoscaling/v2kind: HorizontalPodAutoscalermetadata:  name: production-app-hpaspec:  scaleTargetRef:    apiVersion: apps/v1    kind: Deployment    name: production-app  minReplicas: 3  maxReplicas: 20  metrics:  - type: Resource    resource:      name: cpu      target:        type: Utilization        averageUtilization: 70  - type: Resource    resource:      name: memory      target:        type: Utilization        averageUtilization: 80  - type: Object    object:      metric:        name: requests-per-second      describedObject:        apiVersion: networking.k8s.io/v1        kind: Ingress        name: production-app-ingress      target:        type: Value        value: 1000  behavior:    scaleDown:      stabilizationWindowSeconds: 300      policies:      - type: Percent        value: 10        periodSeconds: 60    scaleUp:      stabilizationWindowSeconds: 60      policies:      - type: Percent        value: 100        periodSeconds: 15&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Key Features:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Multiple metrics&lt;/strong&gt;: CPU, memory, and custom metrics&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Stabilization windows&lt;/strong&gt;: Prevent rapid scaling oscillations&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Conservative scale-down&lt;/strong&gt;: Avoid scaling down too aggressively&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Aggressive scale-up&lt;/strong&gt;: Respond quickly to traffic spikes&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;pro-tip-use-vpa-for-vertical-scaling&quot;&gt;Pro Tip: Use VPA for Vertical Scaling&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#pro-tip-use-vpa-for-vertical-scaling&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;vpa-config.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;autoscaling.k8s.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;VerticalPodAutoscaler&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app-vpa&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;targetRef&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;updatePolicy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;updateMode&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;Off&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Use &amp;quot;Auto&amp;quot; for automatic updates&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;resourcePolicy&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;containerPolicies&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;containerName&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;#39;*&amp;#39;&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;minAllowed&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;100m&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;50Mi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;maxAllowed&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;cpu&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;memory&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;500Mi&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;controlledValues&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;RequestsAndLimits&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: autoscaling.k8s.io/v1kind: VerticalPodAutoscalermetadata:  name: production-app-vpaspec:  targetRef:    apiVersion: apps/v1    kind: Deployment    name: production-app  updatePolicy:    updateMode: &amp;quot;Off&amp;quot;  # Use &amp;quot;Auto&amp;quot; for automatic updates  resourcePolicy:    containerPolicies:    - containerName: &apos;*&apos;      minAllowed:        cpu: 100m        memory: 50Mi      maxAllowed:        cpu: 1        memory: 500Mi      controlledValues: RequestsAndLimits&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;5-backup-and-disaster-recovery-protect-your-data&quot;&gt;5. Backup and Disaster Recovery: Protect Your Data&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#5-backup-and-disaster-recovery-protect-your-data&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;the-3-2-1-backup-rule&quot;&gt;The 3-2-1 Backup Rule&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#the-3-2-1-backup-rule&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;3 copies&lt;/strong&gt; of your data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;2 different storage types&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;1 off-site backup&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;best-practice-automated-backup-strategy&quot;&gt;Best Practice: Automated Backup Strategy&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#best-practice-automated-backup-strategy&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;velero-backup.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;velero.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Schedule&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-daily-backup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;schedule&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;0 2 * * *&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Daily at 2 AM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;includedNamespaces&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;includedResources&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;deployments&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;services&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;configmaps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;secrets&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;persistentvolumeclaims&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;persistentvolumes&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;storageLocation&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-backup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;volumeSnapshotLocations&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-snapshot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ttl&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;720h&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Keep backups for 30 days&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: velero.io/v1kind: Schedulemetadata:  name: production-daily-backupspec:  schedule: &amp;quot;0 2 * * *&amp;quot;  # Daily at 2 AM  template:    includedNamespaces:    - production    includedResources:    - deployments    - services    - configmaps    - secrets    - persistentvolumeclaims    - persistentvolumes    storageLocation: production-backup    volumeSnapshotLocations:    - production-snapshot    ttl: 720h  # Keep backups for 30 days&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h3 id=&quot;backup-verification-strategy&quot;&gt;Backup Verification Strategy&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#backup-verification-strategy&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;backup-verification.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;velero.io/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Schedule&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;backup-verification&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;schedule&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;&amp;quot;0 4 * * 0&amp;quot;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#9FA3AA;--0fs:italic&quot;&gt;# Weekly on Sunday at 4 AM&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;includedNamespaces&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;backup-test&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;includedResources&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;deployments&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;services&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;configmaps&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;secrets&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;persistentvolumeclaims&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;storageLocation&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-backup&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;volumeSnapshotLocations&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;    &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-snapshot&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;ttl&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;24h&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: velero.io/v1kind: Schedulemetadata:  name: backup-verificationspec:  schedule: &amp;quot;0 4 * * 0&amp;quot;  # Weekly on Sunday at 4 AM  template:    includedNamespaces:    - backup-test    includedResources:    - deployments    - services    - configmaps    - secrets    - persistentvolumeclaims    storageLocation: production-backup    volumeSnapshotLocations:    - production-snapshot    ttl: 24h&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;h2 id=&quot;6-deployment-strategies-zero-downtime-updates&quot;&gt;6. Deployment Strategies: Zero-Downtime Updates&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#6-deployment-strategies-zero-downtime-updates&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;rolling-updates-with-health-checks&quot;&gt;Rolling Updates with Health Checks&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#rolling-updates-with-health-checks&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;div class=&quot;expressive-code&quot;&gt;&lt;figure class=&quot;frame has-title&quot;&gt;&lt;figcaption class=&quot;header&quot;&gt;&lt;span class=&quot;title&quot;&gt;rolling-update.yaml&lt;/span&gt;&lt;/figcaption&gt;&lt;pre data-language=&quot;yaml&quot;&gt;&lt;code&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;apiVersion&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;apps/v1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;kind&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;Deployment&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;metadata&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;replicas&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;strategy&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;type&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;RollingUpdate&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;rollingUpdate&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;maxSurge&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;1&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line highlight mark&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#eca3a8&quot;&gt;maxUnavailable&lt;/span&gt;&lt;span style=&quot;--0:#b0b6c3&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#daae84&quot;&gt;0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;  &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;template&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;    &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;spec&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;      &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;containers&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;      &lt;/span&gt;&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;- &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;app&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;production-app:v1.2.0&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;readinessProbe&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;httpGet&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/ready&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;initialDelaySeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;periodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;timeoutSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;failureThreshold&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;        &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;livenessProbe&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;httpGet&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;:&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#98C379&quot;&gt;/health&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;            &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;port&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;8080&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;initialDelaySeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;30&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;periodSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;10&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;timeoutSeconds&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;5&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class=&quot;ec-line&quot;&gt;&lt;div class=&quot;code&quot;&gt;&lt;span class=&quot;indent&quot;&gt;          &lt;/span&gt;&lt;span style=&quot;--0:#E6888F&quot;&gt;failureThreshold&lt;/span&gt;&lt;span style=&quot;--0:#ABB2BF&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;--0:#D19A66&quot;&gt;3&lt;/span&gt;&lt;/div&gt;&lt;/div&gt;&lt;/code&gt;&lt;/pre&gt;&lt;div class=&quot;copy&quot;&gt;&lt;div aria-live=&quot;polite&quot;&gt;&lt;/div&gt;&lt;button title=&quot;Copy to clipboard&quot; data-copied=&quot;Copied!&quot; data-code=&quot;apiVersion: apps/v1kind: Deploymentmetadata:  name: production-appspec:  replicas: 5  strategy:    type: RollingUpdate    rollingUpdate:      maxSurge: 1      maxUnavailable: 0  template:    spec:      containers:      - name: app        image: production-app:v1.2.0        readinessProbe:          httpGet:            path: /ready            port: 8080          initialDelaySeconds: 5          periodSeconds: 5          timeoutSeconds: 3          failureThreshold: 3        livenessProbe:          httpGet:            path: /health            port: 8080          initialDelaySeconds: 30          periodSeconds: 10          timeoutSeconds: 5          failureThreshold: 3&quot;&gt;&lt;div&gt;&lt;/div&gt;&lt;/button&gt;&lt;/div&gt;&lt;/figure&gt;&lt;/div&gt;
&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Zero downtime&lt;/strong&gt;: New pods are ready before old ones are terminated&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Rollback capability&lt;/strong&gt;: Easy to revert to previous version&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Health verification&lt;/strong&gt;: Only healthy pods serve traffic&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;key-takeaways&quot;&gt;Key Takeaways&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#key-takeaways&quot;&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;immediate-actions-you-can-take&quot;&gt;Immediate Actions You Can Take&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#immediate-actions-you-can-take&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Set resource limits&lt;/strong&gt; on all your containers today&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implement health checks&lt;/strong&gt; for every application&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Run containers as non-root&lt;/strong&gt; users&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Set up basic monitoring&lt;/strong&gt; with Prometheus&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Configure HPA&lt;/strong&gt; for your critical applications&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Implement automated backups&lt;/strong&gt; with Velero&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;long-term-strategy&quot;&gt;Long-term Strategy&lt;a class=&quot;heading-anchor&quot; aria-label=&quot;Link to this section&quot; href=&quot;#long-term-strategy&quot;&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Gradually implement&lt;/strong&gt; security policies&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Build comprehensive&lt;/strong&gt; monitoring dashboards&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test disaster recovery&lt;/strong&gt; procedures regularly&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Optimize resource usage&lt;/strong&gt; based on monitoring data&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Automate everything&lt;/strong&gt; possible&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Most importantly, keep it simple! Overcomplicating your infrasturcutre will result in unimaginable growing pains.&lt;/p&gt;
&lt;p&gt;Remember: Production Kubernetes is a journey, not a destination. Start with these fundamentals and continuously improve based on your specific needs and challenges.&lt;/p&gt;
&lt;hr/&gt;
&lt;p&gt;&lt;em&gt;Need help implementing these best practices?&lt;/em&gt; &lt;em&gt;&lt;strong&gt;&lt;a href=&quot;https://join.slack.com/t/ankra-community/shared_invite/zt-3a5rem8f8-cUho4epX2MoLT83bFf~VSA&quot;&gt;Join us on Slack&lt;/a&gt;&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;</content:encoded><dc:creator>Mattias Åsell</dc:creator><category>Best Practices</category><category>Kubernetes</category><category>DevOps</category></item></channel></rss>