{"id":43,"date":"2026-10-01T16:28:25","date_gmt":"2026-10-01T16:28:25","guid":{"rendered":"https:\/\/pomax-v3.weeltec.com\/?p=43"},"modified":"2026-10-01T16:28:25","modified_gmt":"2026-10-01T16:28:25","slug":"gitops-explained-without-jargon","status":"publish","type":"post","link":"https:\/\/pomax-v3.weeltec.com\/?p=43","title":{"rendered":"GitOps Explained Without the Jargon"},"content":{"rendered":"<div class=\"wt-post\">\n<style>.wt-post { --wt-bg: #0A0C0F; --wt-bg-2: #0E1116; --wt-surface: #12161C; --wt-line: #1F252E; --wt-line-strong: #2B333E; --wt-text: #E9ECEF; --wt-muted: #98A2AD; --wt-accent: #B9F24D; --wt-accent-hover: #C8FF5E; --wt-accent-dim: rgba(185, 242, 77, 0.10); --wt-accent-line: rgba(185, 242, 77, 0.25); --wt-danger: #F07A6B; --wt-ok: #7ED99A; --wt-sans: ui-sans-serif, system-ui, -apple-system, \"Segoe UI\", Roboto, \"Helvetica Neue\", Arial, sans-serif; --wt-mono: ui-monospace, \"Cascadia Code\", \"JetBrains Mono\", \"SF Mono\", Menlo, Consolas, monospace; --wt-radius: 4px; --wt-h1: var(--wt-text); --wt-h2: var(--wt-text); --wt-h3: var(--wt-text); box-sizing: border-box; background: var(--wt-bg); color: var(--wt-text); font-family: var(--wt-sans); font-size: 1rem; line-height: 1.7; padding: clamp(1.75rem, 4vw, 3rem); border: 1px solid var(--wt-line); border-radius: 0; -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; } .wt-post *, .wt-post *::before, .wt-post *::after { box-sizing: border-box; } .wt-post ::selection { background: var(--wt-accent); color: var(--wt-bg); } .wt-post.wt-post p { color: var(--wt-text); font-family: var(--wt-sans); font-size: 1rem; line-height: 1.7; margin: 0 0 1.15rem; max-width: 68ch; } .wt-post.wt-post p:last-child { margin-bottom: 0; } .wt-post.wt-post h1, .wt-post.wt-post h2, .wt-post.wt-post h3, .wt-post.wt-post h4, .wt-post.wt-post h5, .wt-post.wt-post h6 { font-family: var(--wt-sans); font-weight: 700; letter-spacing: -0.025em; line-height: 1.15; text-wrap: balance; } .wt-post.wt-post h2 { color: var(--wt-h2); font-size: clamp(1.45rem, 3vw, 2rem); margin: 2.4rem 0 0.9rem; display: flex; align-items: baseline; gap: 0.6rem; } .wt-post.wt-post h2::before { content: \"\"; flex: none; width: 8px; height: 8px; background: var(--wt-accent); transform: translateY(-2px); } .wt-post.wt-post h3 { color: var(--wt-h3); font-size: 1.15rem; font-weight: 650; margin: 1.8rem 0 0.7rem; padding-left: 0.85rem; border-left: 2px solid var(--wt-accent-line); } .wt-post.wt-post h2:first-child, .wt-post.wt-post h3:first-child { margin-top: 0; } .wt-post.wt-post strong { color: #FFFFFF; font-weight: 650; } .wt-post.wt-post em { color: var(--wt-muted); font-style: italic; } .wt-post.wt-post a { color: var(--wt-accent); text-decoration: none; border-bottom: 1px solid var(--wt-accent-line); transition: color 0.15s ease, border-color 0.15s ease; } .wt-post.wt-post a:hover { color: var(--wt-accent-hover); border-bottom-color: var(--wt-accent-hover); } .wt-post.wt-post ul, .wt-post.wt-post ol { margin: 0 0 1.3rem; padding: 0; list-style: none; max-width: 68ch; } .wt-post.wt-post li { position: relative; padding-left: 1.6rem; margin-bottom: 0.55rem; color: var(--wt-text); line-height: 1.65; } .wt-post.wt-post ul > li::before { content: \"\\25AE\"; color: var(--wt-accent); position: absolute; left: 0; top: 0; font-size: 0.85em; line-height: 1.65; } .wt-post.wt-post ol { counter-reset: wt-li; } .wt-post.wt-post ol > li { counter-increment: wt-li; } .wt-post.wt-post ol > li::before { content: counter(wt-li) \".\"; font-family: var(--wt-mono); font-size: 0.8em; color: var(--wt-accent); position: absolute; left: 0; top: 0; line-height: 1.9; } .wt-post.wt-post blockquote { margin: 1.8rem 0; padding: 1.1rem 1.4rem; background: var(--wt-accent-dim); border-left: 2px solid var(--wt-accent); border-radius: 0; color: var(--wt-text); font-size: 1.05rem; font-style: normal; line-height: 1.6; } .wt-post.wt-post blockquote p { margin: 0; color: var(--wt-text); font-style: normal; } .wt-post.wt-post blockquote::before { content: none; } .wt-post.wt-post code, .wt-post.wt-post kbd, .wt-post.wt-post pre { font-family: var(--wt-mono); font-size: 0.88em; } .wt-post.wt-post code { background: var(--wt-surface); border: 1px solid var(--wt-line); border-radius: var(--wt-radius); padding: 0.1em 0.4em; color: var(--wt-accent); } .wt-post.wt-post pre { background: #0C0F13; border: 1px solid var(--wt-line-strong); border-radius: var(--wt-radius); padding: 1.1rem 1.25rem; overflow-x: auto; color: var(--wt-text); line-height: 1.7; margin: 0 0 1.3rem; } .wt-post.wt-post pre code { background: none; border: 0; padding: 0; color: inherit; } .wt-post.wt-post hr { border: 0; border-top: 1px solid var(--wt-line); margin: 2.2rem 0; } .wt-post.wt-post img { max-width: 100%; height: auto; border-radius: var(--wt-radius); border: 1px solid var(--wt-line); } @media (max-width: 640px) { .wt-post.wt-post h2 { font-size: 1.35rem; } .wt-post.wt-post blockquote { padding: 0.9rem 1.1rem; } } @media (prefers-reduced-motion: reduce) { .wt-post.wt-post a { transition: none; } }<\/style>\n<p>GitOps is not a product and not a vendor. Strip away the branding and it is one rule: the desired state of your infrastructure lives in a Git repository, and software inside the cluster continuously makes reality match it.<\/p>\n<p>That is the whole idea. Everything else \u2014 Argo CD, Flux, sync waves, drift detection \u2014 is implementation detail that got mistaken for the concept.<\/p>\n<h2>The one rule, explained<\/h2>\n<p>Traditional deployment means a pipeline runs against the cluster and the cluster ends up as whatever the last few runs left behind. Nobody can say with certainty what is deployed right now, because the answer is spread across shell history and a CI log that rotated out three weeks ago.<\/p>\n<p>GitOps inverts that. The repository is the source of truth. A controller inside the cluster watches the repo, renders the manifests, and compares them to what is actually running. Where they differ, it reconciles. Git becomes the audit log, the rollback mechanism and the documentation at the same time.<\/p>\n<h3>Push versus pull<\/h3>\n<p>Push means CI holds cluster credentials and applies changes from outside. It is simple and familiar, and it means your build system has production access.<\/p>\n<p>Pull means an agent inside the cluster reaches out to Git and collects changes. No external system holds cluster credentials, and every change leaves a trace. This is what people usually mean by GitOps, and it is the model that survives contact with many clusters and many teams.<\/p>\n<ul>\n<li><strong>One repository per environment<\/strong>, or one repo with per-environment overlays via Kustomize or Helm values. Pick one and stay consistent.<\/li>\n<li><strong>Branch strategy is deployment strategy.<\/strong> If a merge to main ships to production, treat main accordingly.<\/li>\n<li><strong>Secrets never belong in plain Git.<\/strong> Use Sealed Secrets, SOPS, or an external secrets operator.<\/li>\n<li><strong>Reconciliation intervals matter.<\/strong> Too slow and drift lingers; too fast and you spend your week arguing with the controller.<\/li>\n<li><strong>Prune is a decision, not a default.<\/strong> Whether deleting a resource from Git deletes it from the cluster is a policy choice with sharp edges.<\/li>\n<\/ul>\n<h2>What it actually fixes<\/h2>\n<p>Drift, first. Someone runs a manual edit at 2 a.m., the fix works, nobody records it, and the next deploy silently reverts it. With a controller watching, that difference surfaces immediately instead of becoming a mystery six weeks later.<\/p>\n<p>Rollback, second. Reverting a commit is a normal, reviewable, well-understood operation rather than a scramble through a release dashboard with a half-remembered password.<\/p>\n<p>Onboarding, third. A new engineer reads the repository and understands the platform. No tribal knowledge required and no hunting for the person who wrote the Terraform in 2021.<\/p>\n<blockquote>\n<p>GitOps does not make deployments safe. It makes them visible, repeatable, and impossible to hide.<\/p>\n<\/blockquote>\n<h2>What it does not fix<\/h2>\n<p>Bad manifests. A controller will faithfully and repeatedly apply a Deployment with no resource requests, a broken readiness probe, or an image tag that does not exist. GitOps guarantees consistency, not correctness. If the desired state is wrong, you get wrong state faster, on schedule, on every cluster at once.<\/p>\n<p>It also does not remove the need for a delivery strategy. Rolling updates, canary releases and progressive delivery are separate concerns; tools such as Argo Rollouts or Flagger sit alongside the GitOps layer, not inside it.<\/p>\n<h3>A realistic starting point<\/h3>\n<p>Pick one non-critical namespace. Install Argo CD or Flux. Point it at a repository containing those manifests. Let it reconcile and watch what happens. Within a day you will learn which resources were being patched by hand, because the controller will quietly revert every one of them.<\/p>\n<h2>How we set it up at Weeltec<\/h2>\n<p>Most engagements begin with a repository structure that matches how the team actually deploys, not an idealised one, because a structure nobody follows is worse than a simple one that sticks. We separate application manifests from cluster add-ons, wire secrets management in from the start instead of bolting it on later, and keep the reconciliation path short enough for an incident responder to reason about under pressure.<\/p>\n<h2>The rule<\/h2>\n<p>If you cannot describe your production state as a commit, you do not have GitOps \u2014 you have scripts and a hopeful pipeline. Start with one namespace, one repository and one controller.<\/p>\n<p><em>We design and operate Kubernetes platforms and the pipelines around them. If your deployments depend on whoever ran them last, <a href=\"https:\/\/weeltec.com\/#contact\">get a quote<\/a> and we will put the state back in Git.<\/em><\/p>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>GitOps is one rule, not a product. Here is what it fixes, what it does not fix, and the smallest realistic setup you can start with this week.<\/p>\n","protected":false},"author":1,"featured_media":42,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[7],"tags":[17,18,9,13],"class_list":["post-43","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-kubernetes","tag-argocd","tag-deployment","tag-gitops","tag-kubernetes"],"_links":{"self":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=43"}],"version-history":[{"count":2,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":79,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/posts\/43\/revisions\/79"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=\/wp\/v2\/media\/42"}],"wp:attachment":[{"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/pomax-v3.weeltec.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}