<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Joonas Venäläinen</title>
    <description>The latest articles on DEV Community by Joonas Venäläinen (@joonvena).</description>
    <link>https://dev.to/joonvena</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1161165%2F4f9b5448-b590-47bc-bfdc-23bda672d1df.jpeg</url>
      <title>DEV Community: Joonas Venäläinen</title>
      <link>https://dev.to/joonvena</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/joonvena"/>
    <language>en</language>
    <item>
      <title>Crossplane: How do providers work</title>
      <dc:creator>Joonas Venäläinen</dc:creator>
      <pubDate>Tue, 17 Oct 2023 07:16:35 +0000</pubDate>
      <link>https://dev.to/polarsquad/crossplane-how-do-providers-work-2fda</link>
      <guid>https://dev.to/polarsquad/crossplane-how-do-providers-work-2fda</guid>
      <description>&lt;p&gt;Providers are the meat around Crossplane’s bones, and they are used to extend the capabilities of Crossplane. When Crossplane is installed, it doesn't have any capabilities to interact with external systems. A core Crossplane pod will only watch the following resources.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;compositeresourcedefinitions.apiextensions.crossplane.io
compositionrevisions.apiextensions.crossplane.io         
compositions.apiextensions.crossplane.io                 
configurationrevisions.pkg.crossplane.io                 
configurations.pkg.crossplane.io                         
controllerconfigs.pkg.crossplane.io                      
locks.pkg.crossplane.io                                  
providerrevisions.pkg.crossplane.io                      
providers.pkg.crossplane.io                              
storeconfigs.secrets.crossplane.io
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When you install a provider, a new pod is created to Crossplane's installation namespace. This pod is a Kubernetes Controller that watches the CRDs that are also installed as part of the provider package.&lt;/p&gt;

&lt;p&gt;To find out what different kinds of providers are available, you can check the &lt;a href="https://marketplace.upbound.io/" rel="noopener noreferrer"&gt;Upbound Marketplace&lt;/a&gt; and &lt;a href="https://github.com/crossplane-contrib" rel="noopener noreferrer"&gt;crossplane-contrib&lt;/a&gt; repository. For this series, we are going to work with the following providers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://marketplace.upbound.io/providers/upbound/provider-gcp-storage/v0.37.0" rel="noopener noreferrer"&gt;provider-gcp-storage&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.upbound.io/providers/upbound/provider-gcp-cloudplatform/v0.37.0" rel="noopener noreferrer"&gt;provider-gcp-cloudplatform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://marketplace.upbound.io/providers/upbound/provider-terraform/v0.10.0" rel="noopener noreferrer"&gt;provider-terraform&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those GCP providers are installed from the &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-family-gcp/v0.37.0/docs" rel="noopener noreferrer"&gt;provider-family-gcp&lt;/a&gt; package. These provider-family packages are special packages that allow you to install only the provider packages you need instead of installing everything, which would mean 343 CRDs if you install the &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-gcp/v0.37.0/docs" rel="noopener noreferrer"&gt;provider-gcp&lt;/a&gt; package instead. Crossplane also states:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;On average, 30 CRDs are used from Provider packages.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Looking at the average number, you would still have ~313 CRDs in the cluster that aren't used 🤯.&lt;/p&gt;

&lt;p&gt;Install the providers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cat &amp;lt;&amp;lt;EOF | kubectl apply --filename=-&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pkg.crossplane.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Provider&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider-gcp-storage&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpkg.upbound.io/upbound/provider-gcp-storage:v0.36.0&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pkg.crossplane.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Provider&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider-gcp-cloudplatform&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpkg.upbound.io/upbound/provider-gcp-cloudplatform:v0.36.0&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pkg.crossplane.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Provider&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider-terraform&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpkg.upbound.io/upbound/provider-terraform:v0.10.0&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a little while, you should see the providers installed and in a healthy state&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get provider
---
NAME                          INSTALLED   HEALTHY   PACKAGE                                                      AGE
provider-gcp-cloudplatform    True        True      xpkg.upbound.io/upbound/provider-gcp-cloudplatform:v0.36.0   116s
provider-gcp-storage          True        True      xpkg.upbound.io/upbound/provider-gcp-storage:v0.36.0         116s
provider-terraform            True        True      xpkg.upbound.io/upbound/provider-terraform:v0.10.0           116s
upbound-provider-family-gcp   True        True      xpkg.upbound.io/upbound/provider-family-gcp:v0.37.0          107s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the providers are installed and ready, we need to set up the ProviderConfig, which configures the credentials for the provider to be able to interact with external systems, in this case, with Google Cloud. You can have multiple ProviderConfigs and reference them in managed resources using &lt;code&gt;providerConfigRef&lt;/code&gt;. ProviderConfigs are cluster-scoped resources.&lt;/p&gt;

&lt;p&gt;You can set up a ProviderConfig per tenant when you have a multi-tenant cluster. When creating compositions, you could patch the value of &lt;code&gt;providerConfigRef&lt;/code&gt; in managed resources with a value of &lt;code&gt;spec.claimRef.namespace&lt;/code&gt;, which points to the namespace where the XRC was created.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdi6k0b4x3rps2ju1hxub.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdi6k0b4x3rps2ju1hxub.png" alt="Multi-tenant providerconfig"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every provider has their own individual settings available when it comes to ProviderConfig. For the GCP provider, you can find all the available configuration options &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-family-gcp/v0.37.0/resources/gcp.upbound.io/ProviderConfig/v1beta1" rel="noopener noreferrer"&gt;here&lt;/a&gt; and for Terraform provider &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-terraform/v0.10.0/resources/tf.upbound.io/ProviderConfig/v1beta1" rel="noopener noreferrer"&gt;here&lt;/a&gt;. If you need to override Controller related settings eg. ServiceAccount you can use &lt;a href="https://doc.crds.dev/github.com/crossplane/crossplane/pkg.crossplane.io/ControllerConfig/v1alpha1" rel="noopener noreferrer"&gt;ControllerConfig&lt;/a&gt; for that.&lt;/p&gt;

&lt;p&gt;In upcoming chapters, we will create resources in Google Cloud that involve creating a bucket, serviceaccount, iam-binding, and serviceaccountkey. Use the following to configure a new service account with needed permissions in GCP:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# GCP Project ID
PROJECT_ID=""

gcloud iam service-accounts create crossplane-sa-demo --display-name "Crossplane Service Account Demo"

gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:crossplane-sa-demo@$PROJECT_ID.iam.gserviceaccount.com --role roles/storage.admin
gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:crossplane-sa-demo@$PROJECT_ID.iam.gserviceaccount.com --role roles/iam.serviceAccountAdmin
gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:crossplane-sa-demo@$PROJECT_ID.iam.gserviceaccount.com --role roles/iam.serviceAccountKeyAdmin
gcloud projects add-iam-policy-binding $PROJECT_ID --member serviceAccount:crossplane-sa-demo@$PROJECT_ID.iam.gserviceaccount.com --role roles/storage.iamMember
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a service account key:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud iam service-accounts keys create credentials.json --iam-account=crossplane-sa-demo@$PROJECT_ID.iam.gserviceaccount.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a Kubernetes secret in &lt;code&gt;crossplane-system&lt;/code&gt; namespace that contains the previously created credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create secret generic gcp-creds --from-file=creds=./credentials.json -n crossplane-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create ProviderConfig that uses these credentials:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cat &amp;lt;&amp;lt;EOF | kubectl apply --filename=-&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcp.upbound.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ProviderConfig&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;projectID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$PROJECT_ID&lt;/span&gt;
  &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Secret&lt;/span&gt;
    &lt;span class="na"&gt;secretRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcp-creds&lt;/span&gt;
    &lt;span class="na"&gt;namespace&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;crossplane-system&lt;/span&gt;
    &lt;span class="na"&gt;key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;creds&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you run this inside GKE, using the Workload Identity for authentication is much better. You can find detailed instructions for it &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-family-gcp/v0.37.0/docs/configuration" rel="noopener noreferrer"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;You can also read the secret from the filesystem using &lt;code&gt;fs&lt;/code&gt;. This might come in handy in cases where you are leveraging, for example, Hashicorp Vault with Vault Agent sidecar to inject secrets to pods. Here is a quick example of how you would configure it without going into too much detail about how to work with Vault Agent Injector:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pkg.crossplane.io/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ControllerConfig&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcp-config&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;vault.hashicorp.com/agent-inject&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
    &lt;span class="na"&gt;vault.hashicorp.com/role&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;crossplane-providers"&lt;/span&gt;
    &lt;span class="s"&gt;...&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;pkg.crossplane.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Provider&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provider-gcp-storage&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;package&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;xpkg.upbound.io/upbound/provider-gcp-storage:v0.36.0&lt;/span&gt;
  &lt;span class="na"&gt;controllerConfigRef&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcp-config&lt;/span&gt;
&lt;span class="nn"&gt;---&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gcp.upbound.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ProviderConfig&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;default&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;projectID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;$PROJECT_ID&lt;/span&gt;
  &lt;span class="na"&gt;credentials&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;source&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Filesystem&lt;/span&gt;
    &lt;span class="na"&gt;fs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;path&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;/vault/secrets/gcp-creds&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now we can quickly test that everything is working by creating a &lt;a href="https://marketplace.upbound.io/providers/upbound/provider-gcp-storage/v0.37.0/resources/storage.gcp.upbound.io/Bucket/v1beta1" rel="noopener noreferrer"&gt;Bucket&lt;/a&gt; resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="s"&gt;cat &amp;lt;&amp;lt;EOF | kubectl apply --filename=-&lt;/span&gt;
&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;storage.gcp.upbound.io/v1beta1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Bucket&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ps-bucket-${RANDOM}&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;forProvider&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;location&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;US&lt;/span&gt;
&lt;span class="s"&gt;EOF&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After a little while, you should see the bucket resource ready and synced:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl get bucket
---
NAME                            READY   SYNCED   EXTERNAL-NAME                  AGE
bucket-crossplane-demo-30855    True    True     bucket-crossplane-demo-30855   15m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, we are ready to start working with GCP using Crossplane. I will go through setting up the Terraform provider configs later in the series when it's time to start working with it.&lt;/p&gt;

&lt;p&gt;Remember to delete the test bucket resource:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl delete bucket &amp;lt;bucket_name&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The next chapter quickly reviews available configuration options for managed resources.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>iac</category>
      <category>crossplane</category>
    </item>
    <item>
      <title>Crossplane: Streamline your infrastructure provisioning &amp; management</title>
      <dc:creator>Joonas Venäläinen</dc:creator>
      <pubDate>Tue, 17 Oct 2023 07:16:15 +0000</pubDate>
      <link>https://dev.to/polarsquad/crossplane-streamline-your-infrastructure-provisioning-management-3hni</link>
      <guid>https://dev.to/polarsquad/crossplane-streamline-your-infrastructure-provisioning-management-3hni</guid>
      <description>&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnus3iufx5kdrnl5k902.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcnus3iufx5kdrnl5k902.png" alt="Crossplane architecture"&gt;&lt;/a&gt;&lt;br&gt;
Crossplane is an extension to Kubernetes, which transforms your Kubernetes cluster into a universal control plane. It allows you to manage anything that has an API available with the help of provider packages. It's also fully extendable, so you can build your own providers to support your APIs. Everybody likes 🍕 so here is a post &lt;a href="https://blog.crossplane.io/providers-101-ordering-pizza-with-kubernetes-and-crossplane" rel="noopener noreferrer"&gt;providers-101-ordering-pizza-with-kubernetes-and-crossplane&lt;/a&gt; which goes through on a high level how to build a provider that is capable of ordering pizza for you inside Kubernetes cluster.&lt;/p&gt;

&lt;p&gt;Crossplane is often used to interact with cloud providers like Azure, AWS, and GCP. By using the Crossplane, you can bring your infrastructure management to Kubernetes. Another significant benefit of Crossplane is that it acts as a &lt;a href="https://kubernetes.io/docs/concepts/architecture/controller/" rel="noopener noreferrer"&gt;Kubernetes Controller&lt;/a&gt;, constantly monitoring the state of external resources. So, if someone would modify/delete the resources outside of Kubernetes, Crossplane would reconcile the resources.&lt;/p&gt;

&lt;p&gt;By connecting Kubernetes and the cloud provider APIs with Kubernetes Custom Resource Definitions (CRDs), Crossplane can be used to enable a Kubernetes-native approach to managing cloud resources. We can for example define a Database custom resource which will then provision a database in the cloud provider that we have hooked Crossplane into. This makes it easier for developers to start consuming infrastructure resources by hiding the complexity behind Crossplane compositions. The Ops team can create and maintain these compositions and the &lt;a href="https://docs.crossplane.io/v1.13/concepts/composite-resource-definitions/" rel="noopener noreferrer"&gt;XRDs&lt;/a&gt; which define how the resource will look like for the consumers. Without going into too much detail, we could have a custom resource &lt;code&gt;Database&lt;/code&gt; that the developers can consume.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;storage.polarsquad.com/v1alpha1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Database&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ps-demo-db-mysql&lt;/span&gt;
&lt;span class="na"&gt;spec&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ps-demo-db-mysql&lt;/span&gt;
    &lt;span class="na"&gt;size&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;small"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, we define the size as &lt;code&gt;small&lt;/code&gt;. The Ops team could set small, medium, and large options for the size. Then, in compositions, patch these values to specific instance types depending on the cloud platform. This also enhances the experience for the developers as they don't have to know the specific instance types.&lt;/p&gt;

&lt;p&gt;As the resources are native Kubernetes manifests, you can bundle them with the other manifests you use to deploy the application to the cluster. When the resources are created, Crossplane will create the connection secrets to the application namespace for pods to consume.&lt;/p&gt;

&lt;p&gt;Overall, the Crossplane allows you to form your own Cloud Platform inside Kubernetes. With the help of compositions, you can build a self-service platform where developers can easily create resources on-demand when they need them without having to jump through hoops to get additional backing services.&lt;/p&gt;

&lt;p&gt;Throughout the series, I will be using the terms &lt;code&gt;XRD&lt;/code&gt;,&lt;code&gt;XR&lt;/code&gt;, and &lt;code&gt;XRS&lt;/code&gt;. Here is a quick overview of what they stand for.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;XRD&lt;/code&gt; - Composite Resource Definition&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XR&lt;/code&gt; - Composite Resource&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;XRC&lt;/code&gt; - Claim&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  Prerequisites:
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Access to Google Cloud and &lt;a href="https://cloud.google.com/sdk/docs/install" rel="noopener noreferrer"&gt;gcloud cli&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Kubernetes cluster eg. &lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;minikube&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://helm.sh/docs/intro/install/" rel="noopener noreferrer"&gt;Helm&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Access to &lt;a href="https://aiven.io/" rel="noopener noreferrer"&gt;Aiven&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Aiven offers a free tier so you can create an account and use it to get through the tutorial.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Install Crossplane
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm repo add crossplane-stable https://charts.crossplane.io/stable
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;helm install crossplane --namespace crossplane-system --create-namespace crossplane-stable/crossplane
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;At this point, the Crossplane is ready, and the next step is to install the needed &lt;a href="https://docs.crossplane.io/latest/concepts/providers/" rel="noopener noreferrer"&gt;Providers&lt;/a&gt; that give the Crossplane capabilities to provision managed resources to external systems.&lt;/p&gt;

&lt;p&gt;In this series, we will provision resources to Google Cloud using the Google Cloud providers and, later in the series, leverage Terraform provider to manage resources that don't have a Crossplane native provider available yet.&lt;/p&gt;

&lt;p&gt;Links to each part of this series:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://dev.to/polarsquad/crossplane-how-do-providers-work-2fda"&gt;Crossplane: How do providers work&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>devops</category>
      <category>kubernetes</category>
      <category>iac</category>
      <category>crossplane</category>
    </item>
  </channel>
</rss>
