<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Terraform Archives - Linuxcent</title>
	<atom:link href="https://linuxcent.com/tag/terraform/feed/" rel="self" type="application/rss+xml" />
	<link>https://linuxcent.com/tag/terraform/</link>
	<description>Infrastructure security, from the kernel up.</description>
	<lastBuildDate>Fri, 10 Jul 2026 15:37:28 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0.2</generator>

<image>
	<url>https://linuxcent.com/wp-content/uploads/2026/04/favicon-512x512-1-150x150.png</url>
	<title>Terraform Archives - Linuxcent</title>
	<link>https://linuxcent.com/tag/terraform/</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">211632295</site>	<item>
		<title>Crossplane vs Terraform: Composition vs HCL for Infrastructure as Code</title>
		<link>https://linuxcent.com/crossplane-vs-terraform/</link>
					<comments>https://linuxcent.com/crossplane-vs-terraform/#respond</comments>
		
		<dc:creator><![CDATA[Vamshi Krishna Santhapuri]]></dc:creator>
		<pubDate>Thu, 23 Jul 2026 02:00:00 +0000</pubDate>
				<category><![CDATA[Kubernetes Ecosystem]]></category>
		<category><![CDATA[Crossplane]]></category>
		<category><![CDATA[Infrastructure as Code]]></category>
		<category><![CDATA[Kubernetes]]></category>
		<category><![CDATA[Terraform]]></category>
		<guid isPermaLink="false">https://linuxcent.com/?p=2255</guid>

					<description><![CDATA[<p><span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 5</span> <span class="rt-label rt-postfix">minutes</span></span>Compare Crossplane's Kubernetes-native composition model to Terraform's HCL state model — and get a clear recommendation, not a neutral list.</p>
<p>The post <a href="https://linuxcent.com/crossplane-vs-terraform/">Crossplane vs Terraform: Composition vs HCL for Infrastructure as Code</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></description>
										<content:encoded><![CDATA[<span class="span-reading-time rt-reading-time" style="display: block;"><span class="rt-label rt-prefix">Reading Time: </span> <span class="rt-time"> 5</span> <span class="rt-label rt-postfix">minutes</span></span><style>
pre{position:relative;background:#1e1e1e;color:#d4d4d4;
    padding:16px 16px 16px 20px;border-radius:6px;overflow-x:auto;
    font-family:'JetBrains Mono','Fira Code','Cascadia Code',Consolas,'Courier New',monospace;
    font-size:.88em;line-height:1.6;border-left:4px solid #555}
code{background:#f4f4f4;padding:2px 5px;border-radius:3px;font-size:.9em}
pre code{background:transparent;padding:0;color:inherit}
pre[data-lang="bash"],pre[data-lang="sh"],
pre[data-lang="shell"],pre[data-lang="zsh"]{border-left-color:#4ec9b0}
pre[data-lang="yaml"],pre[data-lang="json"],
pre[data-lang="toml"],pre[data-lang="xml"]{border-left-color:#569cd6}
pre[data-lang="python"],pre[data-lang="go"],pre[data-lang="rust"],
pre[data-lang="java"],pre[data-lang="c"],pre[data-lang="cpp"]{border-left-color:#c586c0}
pre[data-lang="text"],pre[data-lang="output"],
pre[data-lang="console"]{border-left-color:#888}
.lc-copy-btn{position:absolute;top:8px;right:8px;background:#2d2d2d;color:#ccc;
    border:1px solid #444;border-radius:4px;padding:3px 9px;font-size:.75em;
    font-family:system-ui,sans-serif;cursor:pointer;opacity:0;
    transition:opacity .15s,background .15s;line-height:1.6}
pre:hover .lc-copy-btn{opacity:1}
.lc-copy-btn:hover{background:#3a3a3a;color:#fff}
.lc-copy-btn.copied{color:#4ec9b0;border-color:#4ec9b0}
.lc-lang-badge{position:absolute;top:8px;left:20px;font-family:system-ui,sans-serif;
    font-size:.7em;color:#666;text-transform:uppercase;letter-spacing:.04em;
    line-height:1;pointer-events:none;opacity:0;transition:opacity .15s}
pre:hover .lc-lang-badge{opacity:1}
table{border-collapse:collapse;width:100%;margin:16px 0}
th,td{border:1px solid #ddd;padding:10px 14px;text-align:left}
th{background:#f0f0f0;font-weight:600}
tr:nth-child(even){background:#fafafa}
</style>
<p><script>
(function(){
  if(window.__lcCodeEnhanced)return;
  window.__lcCodeEnhanced=true;
  function enhance(){
    document.querySelectorAll('pre').forEach(function(pre){
      var code=pre.querySelector('code');
      var lang='';
      if(code){var m=(code.className||'').match(/language-(\S+)/);if(m)lang=m[1].toLowerCase();}
      if(lang)pre.setAttribute('data-lang',lang);
      if(lang){var badge=document.createElement('span');badge.className='lc-lang-badge';badge.textContent=lang;pre.insertBefore(badge,pre.firstChild);}
      var btn=document.createElement('button');
      btn.className='lc-copy-btn';btn.textContent='Copy';btn.setAttribute('aria-label','Copy code to clipboard');
      pre.appendChild(btn);
      btn.addEventListener('click',function(){
        var text=code?code.innerText:pre.innerText;
        if(navigator.clipboard&&window.isSecureContext){
          navigator.clipboard.writeText(text).then(function(){ok(btn);}).catch(function(){fb(text,btn);});
        }else{fb(text,btn);}
      });
    });
  }
  function ok(btn){btn.textContent='Copied!';btn.classList.add('copied');setTimeout(function(){btn.textContent='Copy';btn.classList.remove('copied');},2000);}
  function fb(text,btn){
    try{var ta=document.createElement('textarea');ta.value=text;ta.style.cssText='position:fixed;left:-9999px;top:-9999px;opacity:0';document.body.appendChild(ta);ta.select();document.execCommand('copy');document.body.removeChild(ta);ok(btn);}
    catch(e){btn.textContent='✗ Failed';setTimeout(function(){btn.textContent='Copy';},2000);}
  }
  if(document.readyState==='loading'){document.addEventListener('DOMContentLoaded',enhance);}else{enhance();}
})();
</script></p>
<p><em>Kubernetes Ecosystem: From User to Contributor, Episode 7</em><br />
<a href="/crossplane-universal-control-plane/">← EP06: Crossplane</a> · <strong>EP07: Crossplane vs Terraform</strong> · <a href="/karpenter-node-provisioning/">EP08: Karpenter →</a></p>
<p><strong>11 min read</strong></p>
<hr />
<h2 id="tldr">TL;DR</h2>
<ul>
<li>Crossplane vs Terraform is fundamentally a continuous-reconciliation model against a plan/apply model — not just two different syntaxes for the same idea</li>
<li>Crossplane needs a live Kubernetes cluster to run at all; Terraform needs nothing but a state file and network access to the providers it&#8217;s calling</li>
<li>Terraform&#8217;s provider registry is a decade deep and covers services Crossplane&#8217;s younger ecosystem hasn&#8217;t reached yet — SaaS tools, monitoring platforms, and services with no cloud-infrastructure angle at all</li>
<li>Crossplane&#8217;s Compositions give app teams a genuinely self-service, in-cluster API; Terraform&#8217;s modules give infra teams reusable code, but consuming a module still means running Terraform yourself</li>
<li>Recommendation: many real platform teams use both — Terraform (or CAPI, EP05) to bootstrap the cluster and its surrounding VPC/networking, then Crossplane running inside that cluster for the self-service, app-team-facing layer</li>
<li>Contribution opportunity: Crossplane&#8217;s provider coverage gap against Terraform&#8217;s registry is real, specific, and a legitimate place to build a brand-new provider</li>
</ul>
<hr />
<h2 id="the-big-picture">The Big Picture</h2>
<pre><code class="" data-line="">TERRAFORM                                   CROSSPLANE
──────────                                   ──────────
terraform plan                               kubectl apply -f resource.yaml
  │  (shows what WOULD change)                    │
  ▼                                                ▼
terraform apply                              Crossplane controller reconciles
  │  (changes happen once, here)                   │  (continuously, forever,
  ▼                                                 │   not just at apply time)
State file (local or remote backend)               ▼
tracks what Terraform created                 Kubernetes etcd IS the state —
                                                the CR&#039;s status field tracks
No live cluster or control                     sync state
plane required to run this
                                               Requires a running Kubernetes
                                               cluster as the control plane
</code></pre>
<p>Crossplane vs Terraform is best understood through that control-flow difference first, before comparing any specific feature: Terraform changes things at discrete moments you trigger; Crossplane&#8217;s controllers are always watching, always correcting drift, for as long as the cluster runs.</p>
<hr />
<h2 id="the-fundamental-model-difference-continuous-reconciliation-vs-planapply">The Fundamental Model Difference: Continuous Reconciliation vs Plan/Apply</h2>
<p>Terraform&#8217;s model gives you an explicit review step — <code class="" data-line="">terraform plan</code> shows exactly what will change before anything does, and nothing changes again until you run <code class="" data-line="">apply</code> a second time. Crossplane&#8217;s model (covered in EP06) has no equivalent pause: once a Managed Resource or Composition claim exists, Crossplane&#8217;s controllers reconcile it toward the desired state continuously, including reverting manual out-of-band changes automatically.</p>
<p>Neither is objectively better — they&#8217;re suited to different operating assumptions. Terraform&#8217;s model fits teams who want a deliberate, reviewed change process. Crossplane&#8217;s fits teams who want infrastructure to behave like every other Kubernetes-native resource: self-healing, always converging, no separate &#8220;did anyone remember to re-apply&#8221; step.</p>
<hr />
<h2 id="state-management-etcd-crds-vs-terraform-state-files">State Management: etcd + CRDs vs Terraform State Files</h2>
<pre><code class="" data-line=""># Terraform: state lives in a file (local or remote — S3, Terraform Cloud, etc.)
$ terraform state list
aws_s3_bucket.uploads
aws_db_instance.main

# Crossplane: &quot;state&quot; is just the live cluster&#039;s etcd — the CR&#039;s own status
$ kubectl get bucket uploads -o jsonpath=&#039;{.status.conditions}&#039;
[{&quot;type&quot;:&quot;Ready&quot;,&quot;status&quot;:&quot;True&quot;},{&quot;type&quot;:&quot;Synced&quot;,&quot;status&quot;:&quot;True&quot;}]
</code></pre>
<p>Terraform&#8217;s state file is a single point of coordination that has to be locked correctly for concurrent runs to be safe — a well-understood but real operational concern (remote state backends, state locking, occasional manual state surgery after a botched apply). Crossplane sidesteps a separate state file entirely, but that means the health of your Kubernetes cluster&#8217;s etcd <em>is</em> the health of your infrastructure&#8217;s state — a different, not smaller, operational responsibility.</p>
<hr />
<h2 id="composition-vs-modules-reusable-infrastructure-patterns-compared">Composition vs Modules: Reusable Infrastructure Patterns Compared</h2>
<p>Terraform modules are reusable code that whoever runs Terraform includes in their own configuration — genuinely reusable, but still something each consumer runs themselves. Crossplane Compositions (EP06) are reusable <em>inside the cluster</em> — an app team doesn&#8217;t run anything, they just create a custom resource the platform team already defined, and Crossplane&#8217;s controllers do the rest without the app team ever touching Terraform or Crossplane&#8217;s own tooling directly.</p>
<p>That&#8217;s the real practical difference for organizational self-service: Compositions remove the &#8220;app team needs to know how to run our IaC tool&#8221; step entirely. Modules still require the consumer to run Terraform, even if they didn&#8217;t write the module.</p>
<hr />
<h2 id="ecosystem-maturity-terraforms-decade-deep-provider-registry-vs-crossplanes-younger-one">Ecosystem Maturity: Terraform&#8217;s Decade-Deep Provider Registry vs Crossplane&#8217;s Younger One</h2>
<p>Terraform&#8217;s provider registry covers not just the major clouds but a long tail of SaaS platforms, monitoring tools, DNS providers, and internal enterprise systems that have no &#8220;cloud infrastructure&#8221; angle at all — a decade of community and vendor-contributed providers. Crossplane&#8217;s provider ecosystem, while actively growing and covering the major clouds thoroughly, has real, documented gaps once you look past core compute/storage/networking/database resources into more specialized or less common services.</p>
<hr />
<h2 id="the-recommendation-which-one-and-when-to-use-both">The Recommendation: Which One, and When to Use Both</h2>
<p><strong>If your platform team is Kubernetes-native and wants to offer app teams a true self-service infrastructure API without teaching them a separate IaC tool:</strong> Crossplane. That&#8217;s the specific problem its Composition model solves better than anything Terraform offers.</p>
<p><strong>If you need broad provider coverage beyond core cloud infrastructure, or you don&#8217;t want infrastructure lifecycle tied to a live Kubernetes control plane&#8217;s uptime:</strong> Terraform. Its registry depth and its independence from any running cluster are real advantages Crossplane doesn&#8217;t currently match.</p>
<p><strong>The honest answer for a lot of real platform teams is both, at different layers.</strong> Use Terraform (or Cluster API, EP05) to bootstrap the Kubernetes cluster itself and its surrounding cloud networking — the layer that has to exist before Crossplane can run at all — then run Crossplane inside that cluster for the ongoing, self-service, app-team-facing infrastructure requests. This isn&#8217;t a compromise; it&#8217;s matching each tool to the layer it&#8217;s actually better suited for.</p>
<hr />
<h2 id="production-gotchas"><img src="https://s.w.org/images/core/emoji/17.0.2/72x72/26a0.png" alt="⚠" class="wp-smiley" style="height: 1em; max-height: 1em;" /> Production Gotchas</h2>
<p><strong>Don&#8217;t manage the same cloud resource with both Terraform and Crossplane simultaneously.</strong> Both tools will detect the other&#8217;s changes as drift and fight to revert them — pick one owner per resource, even when both tools are in use across your stack at different layers.</p>
<p><strong>Terraform&#8217;s plan/apply gives you a review window Crossplane doesn&#8217;t — build your own review gate if you need one with Crossplane</strong> (a PR-based GitOps flow with required approval before a claim manifest merges is the common substitute).</p>
<p><strong>Crossplane&#8217;s continuous reconciliation means a broken provider or a cloud API outage shows up as a stuck <code class="" data-line="">Synced: False</code> condition, not a failed one-time command</strong> — monitoring needs to watch for stuck conditions over time, not just command exit codes the way Terraform CI pipelines typically do.</p>
<hr />
<h2 id="quick-reference">Quick Reference</h2>
<table>
<thead>
<tr>
<th></th>
<th>Terraform</th>
<th>Crossplane</th>
</tr>
</thead>
<tbody>
<tr>
<td>Change model</td>
<td>Plan → Apply (explicit)</td>
<td>Continuous reconciliation</td>
</tr>
<tr>
<td>Requires a live cluster</td>
<td>No</td>
<td>Yes</td>
</tr>
<tr>
<td>State</td>
<td>State file (local/remote)</td>
<td>Kubernetes etcd + CR status</td>
</tr>
<tr>
<td>Reusable patterns</td>
<td>Modules (you still run them)</td>
<td>Compositions (app team just creates a claim)</td>
</tr>
<tr>
<td>Provider breadth</td>
<td>Very broad, decade-deep</td>
<td>Growing, strong on core cloud, gaps elsewhere</td>
</tr>
<tr>
<td>Manual drift</td>
<td>Detected at next <code class="" data-line="">plan</code>, not auto-reverted</td>
<td>Auto-reverted on next reconcile</td>
</tr>
</tbody>
</table>
<hr />
<h2 id="contribution-opportunity-building-a-missing-crossplane-provider">Contribution Opportunity: Building a Missing Crossplane Provider</h2>
<p><strong>The limitation:</strong> For a meaningful number of services Terraform has supported for years — smaller SaaS platforms, specialized monitoring tools, niche infrastructure services — there&#8217;s no Crossplane provider equivalent yet. Anyone wanting to manage that service the Crossplane way currently can&#8217;t, full stop.</p>
<p><strong>Why it&#8217;s hard to fix:</strong> Building a new provider means implementing a real API client, defining CRD schemas that faithfully map the service&#8217;s actual parameters, and maintaining it as that service&#8217;s API evolves — real, ongoing engineering commitment, not a one-time script. That&#8217;s exactly why the ecosystem&#8217;s provider list still trails Terraform&#8217;s, despite Crossplane&#8217;s core reconciliation engine being mature: the core is one thing to maintain, but each provider is its own ongoing surface area.</p>
<p><strong>What a contribution-shaped fix looks like:</strong> Crossplane&#8217;s <code class="" data-line="">provider-template</code> repository exists specifically to make starting a new provider tractable — it scaffolds the boilerplate (code generation, CRD structure, controller wiring) so a new provider author focuses on the actual API mapping, not plumbing. Picking one service you already use via Terraform that has no Crossplane equivalent, and building a minimal provider covering just the 2-3 resource types you actually need, is a real, bounded, achievable contribution — and one the Crossplane community actively wants, given how directly it grows the ecosystem.</p>
<hr />
<h2 id="key-takeaways">Key Takeaways</h2>
<ul>
<li>Crossplane&#8217;s continuous reconciliation and Terraform&#8217;s plan/apply are different operating models, not different syntaxes for the same thing — pick based on which review/change process fits your team</li>
<li>Crossplane requires a live cluster to function at all; Terraform doesn&#8217;t, which matters for bootstrapping order</li>
<li>Compositions remove the &#8220;app team has to run our IaC tool&#8221; step that Terraform modules still require</li>
<li>Terraform&#8217;s provider registry breadth remains a real advantage for anything beyond core cloud infrastructure</li>
<li>Many real platform teams run both at different layers — Terraform/CAPI to bootstrap the cluster, Crossplane inside it for self-service — and that&#8217;s a legitimate architecture, not indecision</li>
</ul>
<hr />
<h2 id="whats-next">What&#8217;s Next</h2>
<p>Everything so far in this series has been about provisioning clusters and the infrastructure around them. EP08 shifts to what happens inside an already-running cluster when pods can&#8217;t be scheduled: Karpenter&#8217;s just-in-time node provisioning, and why it replaced the node-group model most teams started with.</p>
<p><em>Next: <a href="/karpenter-node-provisioning/">EP08 — Karpenter: Just-in-Time Node Provisioning for Kubernetes</a></em></p>
<p>Get EP08 in your inbox when it publishes → <a href="https://linuxcent.com/subscribe">linuxcent.com/subscribe</a></p>
<p><a class="a2a_button_mastodon" href="https://www.addtoany.com/add_to/mastodon?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="Mastodon" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_reddit" href="https://www.addtoany.com/add_to/reddit?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="Reddit" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_x" href="https://www.addtoany.com/add_to/x?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="X" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_copy_link" href="https://www.addtoany.com/add_to/copy_link?linkurl=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&amp;linkname=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" title="Copy Link" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Flinuxcent.com%2Fcrossplane-vs-terraform%2F&#038;title=Crossplane%20vs%20Terraform%3A%20Composition%20vs%20HCL%20for%20Infrastructure%20as%20Code" data-a2a-url="https://linuxcent.com/crossplane-vs-terraform/" data-a2a-title="Crossplane vs Terraform: Composition vs HCL for Infrastructure as Code"></a></p><p>The post <a href="https://linuxcent.com/crossplane-vs-terraform/">Crossplane vs Terraform: Composition vs HCL for Infrastructure as Code</a> appeared first on <a href="https://linuxcent.com">Linuxcent</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://linuxcent.com/crossplane-vs-terraform/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">2255</post-id>	</item>
	</channel>
</rss>

<!--
Performance optimized by W3 Total Cache. Learn more: https://www.boldgrid.com/w3-total-cache/?utm_source=w3tc&utm_medium=footer_comment&utm_campaign=free_plugin

Page Caching using Disk: Enhanced 

Served from: linuxcent.com @ 2026-07-24 02:44:29 by W3 Total Cache
-->