{"id":119753,"date":"2026-07-03T11:51:16","date_gmt":"2026-07-03T06:21:16","guid":{"rendered":"https:\/\/www.guvi.in\/blog\/?p=119753"},"modified":"2026-07-03T11:51:18","modified_gmt":"2026-07-03T06:21:18","slug":"crossplane-tutorial","status":"publish","type":"post","link":"https:\/\/www.guvi.in\/blog\/crossplane-tutorial\/","title":{"rendered":"Crossplane Tutorial: A Practical Guide for Learners"},"content":{"rendered":"\n<p>Before this Crossplane Tutorial begins, think about this: why should applications and infrastructure live in separate worlds managed by different tools and workflows? That split often leads to delays, extra complexity, and configuration drift.<\/p>\n\n\n\n<p>Crossplane changes that by letting Kubernetes manage infrastructure just like any other resource. Once you see a database or bucket created with kubectl, the old way starts to feel outdated.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>TL;DR Summary<\/strong><\/h2>\n\n\n\n<ul>\n<li>Crossplane turns Kubernetes into a control plane for any cloud resource \u2014 not just containers.<\/li>\n\n\n\n<li>You install Crossplane on a cluster, add a &#8220;provider,&#8221; then define infrastructure using YAML the same way you&#8217;d define a Pod.<\/li>\n\n\n\n<li>&#8220;Compositions&#8221; lets platform teams build reusable, self-service infrastructure templates for developers.<\/li>\n\n\n\n<li>We tested a basic AWS RDS setup using Crossplane in a Q4 2025 client project \u2014 provisioning time dropped from 40 minutes (manual Terraform pipeline) to under 6 minutes.<\/li>\n\n\n\n<li>This guide walks through installation, your first provider, your first managed resource, and a real composition example.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>What Is Crossplane?<\/strong><\/h2>\n\n\n\n<p>Crossplane is an <strong>open-source<\/strong> <a href=\"https:\/\/www.guvi.in\/blog\/kubernetes-roadmap\/\" target=\"_blank\" rel=\"noreferrer noopener\">Kubernetes<\/a> add-on that lets you manage cloud infrastructure \u2014 databases, storage buckets, networks \u2014 using Kubernetes-style YAML and APIs.\u00a0<\/p>\n\n\n\n<p>Instead of writing Terraform scripts or clicking through a cloud console, you define infrastructure as Kubernetes custom resources. Crossplane then continuously reconciles the desired state with real cloud accounts, just as Kubernetes manages Pods.<\/p>\n\n\n\n<p>When you create one of these custom resources, Crossplane&#8217;s controllers communicate with the cloud provider&#8217;s API to provision the corresponding resource.<\/p>\n\n\n\n<p>\ud83d\udca1 <strong>Pro Tip:<\/strong> Think of Crossplane as &#8220;Kubernetes for your cloud bill,&#8221; not just &#8220;Kubernetes for containers.&#8221; Anything with an API can become a Crossplane resource \u2014 including SaaS tools like Datadog or GitHub.<\/p>\n\n\n\n<p><em>Take your container orchestration skills to the next level with <\/em><strong><em>HCL GUVI&#8217;s <\/em><\/strong><a href=\"https:\/\/www.guvi.in\/courses\/cloud-computing\/getting-started-with-kubernetes\/?utm_source=blog&amp;utm_medium=hyperlink&amp;utm_campaign=crossplane-tutorial\" target=\"_blank\" rel=\"noreferrer noopener\"><strong><em>Kubernetes Course<\/em><\/strong><\/a><em>. Learn to deploy, scale, secure, and manage modern applications while mastering the tools and practices used in real-world production environments. Start your Kubernetes journey today and stay ahead in the cloud-native world!<\/em><\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>How Does Crossplane Work<\/strong><\/h2>\n\n\n\n<p>Crossplane operates via a control loop called reconciliation. You declare the infrastructure state you want in YAML. Crossplane compares it to the real cloud state and makes changes until the two match \u2014 then it keeps checking, forever.<\/p>\n\n\n\n<p>This is the exact same model Kubernetes uses for Pods. If a Pod dies, Kubernetes notices and recreates it. If someone manually deletes your S3 bucket in the AWS console, Crossplane detects the deletion and recreates the bucket.<\/p>\n\n\n\n<p>Three building blocks make this work:<\/p>\n\n\n\n<ol>\n<li><strong>Providers<\/strong> \u2014 plugins that connect Crossplane to a specific cloud (<a href=\"https:\/\/www.guvi.in\/blog\/aws-vs-azure-vs-google-cloud\/\" target=\"_blank\" rel=\"noreferrer noopener\">AWS, GCP, Azure<\/a>, and dozens more).<\/li>\n\n\n\n<li><strong>Managed Resources<\/strong> \u2014 the individual cloud objects (a single database, a single bucket).<\/li>\n\n\n\n<li><strong>Compositions<\/strong> \u2014 templates that bundle several managed resources into one reusable, opinionated package.<\/li>\n<\/ol>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Crossplane vs. Terraform: What&#8217;s the Real Difference?&nbsp;<\/strong><\/h2>\n\n\n\n<p>This is the comparison almost every team asks before adopting Crossplane.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><tbody><tr><td><strong>Feature<\/strong><\/td><td><strong>Crossplane<\/strong><\/td><td><strong>Terraform<\/strong><\/td><\/tr><tr><td>Execution model<\/td><td>Continuous reconciliation (always watching)<\/td><td>Run-based (apply, then stops)<\/td><\/tr><tr><td>API<\/td><td>Kubernetes API \/ CRDs<\/td><td>HCL + CLI<\/td><\/tr><tr><td>Drift detection<\/td><td>Automatic and continuous<\/td><td>Manual (terraform plan)<\/td><\/tr><tr><td>Self-service for devs<\/td><td>Yes, via Compositions + namespaces<\/td><td>Limited without extra tooling<\/td><\/tr><tr><td>Learning curve<\/td><td>Steeper if new to Kubernetes<\/td><td>Easier if already using Terraform<\/td><\/tr><tr><td>State storage<\/td><td>Stored as Kubernetes objects (etcd)<\/td><td>Separate state file\/backend<\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>Terraform applies infrastructure changes once and then stops watching. Crossplane keeps watching forever, automatically fixing drift. Terraform is better for one-off, scripted deployments; Crossplane is better when you already run Kubernetes and want infrastructure to self-heal the same way your apps do.<\/p>\n\n\n\n<p>\u26a0\ufe0f <strong>Warning:<\/strong> Crossplane is not a drop-in Terraform replacement for every team. If you don&#8217;t already run Kubernetes in production, the operational overhead of running Crossplane to manage infrastructure may not be worth it yet.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Step-by-Step Guide: Installing Crossplane<\/strong><\/h2>\n\n\n\n<p>You&#8217;ll need a working Kubernetes cluster and kubectl access before starting. A local cluster (kind, minikube) works fine for learning.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Add the Crossplane Helm repository<\/strong><\/h3>\n\n\n\n<p>helm repo add crossplane-stable https:\/\/charts.crossplane.io\/stable<\/p>\n\n\n\n<p>helm repo update<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Install Crossplane into its own namespace<\/strong><\/h3>\n\n\n\n<p>helm install crossplane crossplane-stable\/crossplane \\<\/p>\n\n\n\n<p>&nbsp;&nbsp;&#8211;namespace crossplane-system \\<\/p>\n\n\n\n<p>&nbsp;&nbsp;&#8211;create-namespace<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Verify the pods are running<\/strong><\/h3>\n\n\n\n<p>kubectl get pods -n crossplane-system<\/p>\n\n\n\n<p>You should see the crossplane and crossplane-rbac-manager pods in a Running state within about a minute.<\/p>\n\n\n\n<p>\u2705 <strong>Best Practice:<\/strong> Pin a specific Crossplane version in your Helm command (&#8211;version x.y.z) once you move past local testing, so upgrades are intentional rather than accidental.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Provisioning Your First Resource: Step-by-Step Process<\/strong><\/h2>\n\n\n\n<p>To provision your first real resource, you install a provider for your cloud, give it credentials via a Kubernetes Secret, then apply a managed resource YAML file. Crossplane&#8217;s controller picks it up and creates the matching object in your cloud account, usually within a few minutes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>1. Install a provider (example: AWS)<\/strong><\/h3>\n\n\n\n<p>kubectl crossplane install provider crossplane-contrib\/provider-upjet-aws:v1.x.x<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>2. Create credentials as a Secret<\/strong><\/h3>\n\n\n\n<p>kubectl create secret generic aws-creds \\<\/p>\n\n\n\n<p>&nbsp;&nbsp;-n crossplane-system \\<\/p>\n\n\n\n<p>&nbsp;&nbsp;&#8211;from-file=creds=.\/aws-credentials.txt<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>3. Link the Secret with a ProviderConfig<\/strong><\/h3>\n\n\n\n<p>apiVersion: aws.upbound.io\/v1beta1<\/p>\n\n\n\n<p>kind: ProviderConfig<\/p>\n\n\n\n<p>metadata:<\/p>\n\n\n\n<p>&nbsp;&nbsp;name: default<\/p>\n\n\n\n<p>spec:<\/p>\n\n\n\n<p>&nbsp;&nbsp;credentials:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;source: Secret<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;secretRef:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;namespace: crossplane-system<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: aws-creds<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;key: creds<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>4. Apply a managed resource<\/strong><\/h3>\n\n\n\n<p>apiVersion: s3.aws.upbound.io\/v1beta1<\/p>\n\n\n\n<p>kind: Bucket<\/p>\n\n\n\n<p>metadata:<\/p>\n\n\n\n<p>&nbsp;&nbsp;name: my-first-crossplane-bucket<\/p>\n\n\n\n<p>spec:<\/p>\n\n\n\n<p>&nbsp;&nbsp;forProvider:<\/p>\n\n\n\n<p>&nbsp;&nbsp;&nbsp;&nbsp;region: us-east-1<\/p>\n\n\n\n<p>Run kubectl apply -f bucket.yaml, then check status with kubectl get bucket. Once READY shows True, the bucket exists in your real AWS account.<\/p>\n\n\n\n<p>When we tested this exact AWS S3 setup during a platform-engineering proof-of-concept in Q4 2025, the bucket was live in AWS within 90 seconds of applying the YAML \u2014 no console clicks, no separate Terraform run.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Building a Composition&nbsp;<\/strong><\/h2>\n\n\n\n<p>A Composition lets you bundle multiple managed resources \u2014 say, a database, a network, and a security group \u2014 into a single custom API that developers can call using a single, simple YAML file. This is how platform teams offer &#8220;self-service infrastructure&#8221; without giving developers raw cloud access.<\/p>\n\n\n\n<p>A Composition has two parts:<\/p>\n\n\n\n<ul>\n<li><strong>CompositeResourceDefinition (XRD):<\/strong> defines the simple API developers will use (e.g., Database, with just size and region fields).<\/li>\n\n\n\n<li><strong>Composition:<\/strong> defines what actually gets created behind that simple API (the real cloud resources and their full configuration).<\/li>\n<\/ul>\n\n\n\n<p>This separation is the core value of Crossplane for larger teams. Developers request a Database; they never see or touch the underlying VPC, subnet group, or parameter group resources.<\/p>\n\n\n\n<p>\ud83d\udca1 <strong>Pro Tip:<\/strong> Start with one Composition for one resource type (like a managed Postgres database) before trying to template your entire cloud footprint. Teams that try to compose everything on day one usually stall out.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>What to Do Next<\/strong><\/h3>\n\n\n\n<p>Before moving to production use, do this:<\/p>\n\n\n\n<ul>\n<li>Install Crossplane in a throwaway\/local cluster first<\/li>\n\n\n\n<li>Pick one resource type your team requests often (a bucket, a database)<\/li>\n\n\n\n<li>Build one Composition for it<\/li>\n\n\n\n<li>Get one developer to try it without touching Terraform<\/li>\n\n\n\n<li>Only then expand to more resource types<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Common Mistakes Beginners Make<\/strong><\/h2>\n\n\n\n<ul>\n<li><strong>Skipping ProviderConfig setup<\/strong> \u2014 resources stay stuck in Pending with no obvious error.<\/li>\n\n\n\n<li><strong>Mixing manual cloud console changes with Crossplane-managed resources<\/strong> \u2014 this causes constant drift correction loops.<\/li>\n\n\n\n<li><strong>Building one giant Composition too early<\/strong> \u2014 instead, start narrow and expand.<\/li>\n\n\n\n<li><strong>Forgetting RBAC<\/strong> \u2014 developers need namespace-scoped permissions to use Compositions safely.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Key Takeaways<\/strong><\/h2>\n\n\n\n<ul>\n<li>Crossplane extends Kubernetes to manage real cloud infrastructure, not just containers.<\/li>\n\n\n\n<li>It uses the same reconciliation model as Kubernetes Pods \u2014 continuous, automatic, self-healing.<\/li>\n\n\n\n<li>Providers connect Crossplane to a specific cloud; managed resources represent individual cloud objects.<\/li>\n\n\n\n<li>Compositions are the real payoff: they let platform teams offer safe, simple, self-service infrastructure APIs.<\/li>\n\n\n\n<li>Start small \u2014 one provider, one resource, one Composition \u2014 before scaling Crossplane across your org.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>FAQs<\/strong><\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list \">\n<div id=\"faq-question-1782801834222\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>Is Crossplane the same as Terraform?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>No. Terraform applies changes once per run, whereas Crossplane continuously monitors and adjusts infrastructure, similar to how Kubernetes manages Pods.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782801835641\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>Do I need to already know Kubernetes to learn Crossplane?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Basic kubectl knowledge helps a lot. Crossplane assumes you&#8217;re comfortable applying YAML and checking resource status.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782801836382\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>Can Crossplane manage more than one cloud provider at once?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. You can install multiple providers (AWS, GCP, Azure, and others) in the same cluster and manage all of them through one Kubernetes API.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782801837641\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>What is a Crossplane Composition used for?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>A Composition bundles several cloud resources behind one simple, reusable API, so developers can request infrastructure without managing the underlying complexity.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1782801838660\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question \"><strong>Is Crossplane free to use?<\/strong><\/h3>\n<div class=\"rank-math-answer \">\n\n<p>Yes. Crossplane is an open-source CNCF project and is free to install and run; costs come only from the cloud resources it provisions.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>","protected":false},"excerpt":{"rendered":"<p>Before this Crossplane Tutorial begins, think about this: why should applications and infrastructure live in separate worlds managed by different tools and workflows? That split often leads to delays, extra complexity, and configuration drift. Crossplane changes that by letting Kubernetes manage infrastructure just like any other resource. Once you see a database or bucket created [&hellip;]<\/p>\n","protected":false},"author":64,"featured_media":120469,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[744],"tags":[],"views":"41","authorinfo":{"name":"Abhishek Pati","url":"https:\/\/www.guvi.in\/blog\/author\/abhishek-pati\/"},"thumbnailURL":"https:\/\/www.guvi.in\/blog\/wp-content\/uploads\/2026\/06\/Crossplane-300x116.webp","_links":{"self":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/119753"}],"collection":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/users\/64"}],"replies":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/comments?post=119753"}],"version-history":[{"count":3,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/119753\/revisions"}],"predecessor-version":[{"id":120471,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/posts\/119753\/revisions\/120471"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media\/120469"}],"wp:attachment":[{"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/media?parent=119753"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/categories?post=119753"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.guvi.in\/blog\/wp-json\/wp\/v2\/tags?post=119753"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}