<?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>Forem: Javier Sepúlveda</title>
    <description>The latest articles on Forem by Javier Sepúlveda (@segoja7).</description>
    <link>https://forem.com/segoja7</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%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png</url>
      <title>Forem: Javier Sepúlveda</title>
      <link>https://forem.com/segoja7</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/segoja7"/>
    <language>en</language>
    <item>
      <title>Using KIRO and AMDF MCP to Build Reusable Kubernetes KRO Packages</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Sat, 14 Mar 2026 21:16:19 +0000</pubDate>
      <link>https://forem.com/aws-builders/kiro-and-amdf-mcp-for-create-reusable-packages-for-kubernetes-with-kro-gig</link>
      <guid>https://forem.com/aws-builders/kiro-and-amdf-mcp-for-create-reusable-packages-for-kubernetes-with-kro-gig</guid>
      <description>&lt;p&gt;Continuing our journey with KCL, in this post we will explore how to accelerate the creation of reusable Kubernetes packages from CRDs using KIRO and the AMDF MCP tool.&lt;/p&gt;

&lt;p&gt;Kiro + AMDF MCP elevate a process that traditionally requires long times in a conversation of minutes, where the developer simply indicates what resources are needed.&lt;/p&gt;

&lt;p&gt;Additionally, by using KCL instead of traditional YAML, KCL provides strong typing, validation at development time, and abstraction capabilities that transform repetitive configurations into reusable and maintainable code. The result is infrastructure as data that is not only generated quickly, but is also robust, validated, and ready.&lt;/p&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster&lt;/li&gt;
&lt;li&gt;CRDS in Kubernetes Cluster, for this demo &lt;a href="https://aws-controllers-k8s.github.io/docs/getting-started/" rel="noopener noreferrer"&gt;ACK&lt;/a&gt;, &lt;a href="https://kro.run/docs/getting-started/Installation" rel="noopener noreferrer"&gt;KRO&lt;/a&gt; and &lt;a href="https://external-secrets.io/latest/introduction/getting-started/" rel="noopener noreferrer"&gt;External Secrets Operator&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="https://amdf.readthedocs.io/en/latest/" rel="noopener noreferrer"&gt;AMDF&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kiro.dev/" rel="noopener noreferrer"&gt;KIRO&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kcl-lang.io/docs/user_docs/getting-started/install" rel="noopener noreferrer"&gt;KCL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F12kq9ybkj5fzx9ikqvs1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F12kq9ybkj5fzx9ikqvs1.png" alt="KRO-ACK-ESO CRDS" width="800" height="358"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;Validate your CRDS.&lt;br&gt;
In this case the cluster have CRDS from ESO and ACK EC2-RDS Controllers.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Faoh2dfjehbc5eg9x4m3i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Faoh2dfjehbc5eg9x4m3i.png" alt="EC2 ACK Controllers" width="800" height="313"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffwaonq0h38oxvywu7f1i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffwaonq0h38oxvywu7f1i.png" alt="Kro CRDS" width="800" height="64"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;Connect MCP.&lt;br&gt;
With AMDF installed is so simple like as execute&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;amdf mcp-server 
Starting AMDF MCP Server...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;p&gt;With the MCP Server running, open KIRO for start to create reusable packages using a basic prompt.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kiro, I need to create a ResourceGraphDefinition CRD KCL schema for generate an abstraction of multiple resources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbpnmnhvvl89grtlrhh4c.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbpnmnhvvl89grtlrhh4c.png" alt="KIRO Prompt KCL" width="499" height="314"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 4.
&lt;/h2&gt;

&lt;p&gt;With the prompt running, the AMDF MCP tools start to working.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjhkugacsp12m91pq1g5d.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjhkugacsp12m91pq1g5d.png" alt="KIRO PROMPT AMDF MCP SERVER" width="499" height="175"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ff7imeu4uw66ci3xa4lrw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ff7imeu4uw66ci3xa4lrw.png" alt="KIRO PROMPT KCL AMDF" width="502" height="197"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 5.
&lt;/h2&gt;

&lt;p&gt;AMDF Automatically create this directorys using KCL sintax.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fzxr8hefqed1nw6rn58sn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzxr8hefqed1nw6rn58sn.png" alt="AMDF MCP SCALLFODER description" width="302" height="236"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 6.
&lt;/h2&gt;

&lt;p&gt;For this demo, I migrated a code from crossplane to KRO, using &lt;br&gt;
helper functions and CEL expretions required for KRO.&lt;/p&gt;

&lt;p&gt;Check the code in this repository &lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/mcp-kcl-infra-accelerator" rel="noopener noreferrer"&gt;
        mcp-kcl-infra-accelerator
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      Kubernetes packages using KRO, KCL, and MCP (KIRO + AMDF).
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Keycloak Stack&lt;/h1&gt;
&lt;/div&gt;

&lt;p&gt;A reusable Keycloak deployment abstraction built with KRO and KCL. It provisions Keycloak and its database backend — either a local PostgreSQL instance or AWS RDS — from a single Kubernetes custom resource.&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a rel="noopener noreferrer" href="https://github.com/segoja7/mcp-kcl-infra-accelerator/KRO-KEYCLOAK-1.drawio.png"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fraw.githubusercontent.com%2Fsegoja7%2Fmcp-kcl-infra-accelerator%2FHEAD%2FKRO-KEYCLOAK-1.drawio.png" alt="Keycloak Stack Architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Description&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;This example demonstrates how to use KCL to define a KRO &lt;strong&gt;ResourceGraphDefinition&lt;/strong&gt; that generates a &lt;code&gt;KeycloakStack&lt;/code&gt; CRD. Applying a &lt;code&gt;KeycloakStack&lt;/code&gt; instance creates all the necessary Kubernetes resources for a fully functional Keycloak deployment.&lt;/p&gt;

&lt;p&gt;The stack supports two deployment modes controlled by the &lt;code&gt;localTest&lt;/code&gt; flag:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Local mode&lt;/strong&gt; (&lt;code&gt;localTest: true&lt;/code&gt;) — Deploys an in-cluster PostgreSQL Deployment, Service, and Secret. Ideal for development and testing.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS RDS mode&lt;/strong&gt; (&lt;code&gt;localTest: false&lt;/code&gt;) — Provisions an AWS RDS DBInstance with optional subnet group and security group, and connects Keycloak via an ExternalName Service. Supports three password management strategies.&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project Structure&lt;/h2&gt;

&lt;/div&gt;

&lt;div class="snippet-clipboard-content notranslate position-relative overflow-auto"&gt;
&lt;pre class="notranslate"&gt;&lt;code&gt;
├── KRO-KEYCLOAK-1.drawio.png          # Architecture diagram
├── kcl_render/
│   └── KeycloakStack.yaml             # Rendered YAML output&lt;/code&gt;&lt;/pre&gt;…&lt;/div&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/segoja7/mcp-kcl-infra-accelerator" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 7.
&lt;/h3&gt;

&lt;p&gt;Check the Main.k&lt;br&gt;
New to KCL? Don't worry! The syntax is designed to be developer-friendly. You can find a complete introduction in my previous &lt;a href="https://dev.to/segoja7/kcl-for-managing-infraestructure-as-data-n7a"&gt;blog&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Is time for test that code is correctly and compile.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1yl3rrxeyn36yjxn8dgb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1yl3rrxeyn36yjxn8dgb.png" alt="kcl library/main.k" width="617" height="459"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3&gt;
  
  
  Step 8.
&lt;/h3&gt;

&lt;p&gt;Test that new KCL package using AMDF, KIRO and RDS, EC2 ACK and External Secrets Controllers are working correctly.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;kcl library/main.k | kubectl apply -f -
resourcegraphdefinition.kro.run/keycloak-stack created
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here's an RGD that creates a new KeycloakStack API. When users create an KeycloakStack, kro automatically creates multiples resources defined in the Resource Graph Definition&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjsfubpq7fi5fy86g7m9m.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjsfubpq7fi5fy86g7m9m.png" alt="resource graph definition kro" width="800" height="41"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For now, this is a local test, but let me show you how to bring this to GitOps and integrate it with OCI registries and using the KCL plugin for deployment in the next blog.&lt;/p&gt;

&lt;h3&gt;
  
  
  Step 9.
&lt;/h3&gt;

&lt;p&gt;check the 02-aws-rds-deploy.yaml.&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;kro.run/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;KeycloakStack&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;keycloak-dev&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;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;projectName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dev"&lt;/span&gt;
  &lt;span class="na"&gt;environment&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;dev"&lt;/span&gt;
  &lt;span class="na"&gt;keycloakMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;start-dev"&lt;/span&gt;
  &lt;span class="na"&gt;keycloakReplicas&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
  &lt;span class="na"&gt;kcProxy&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;  &lt;span class="c1"&gt;# Sin proxy para port-forward  &lt;/span&gt;
  &lt;span class="na"&gt;keycloakImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;quay.io/keycloak/keycloak:latest"&lt;/span&gt;
  &lt;span class="na"&gt;keycloakAdminUser&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;admin"&lt;/span&gt;
  &lt;span class="na"&gt;keycloakHostname&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keycloakrds.local"&lt;/span&gt;
  &lt;span class="na"&gt;postgresImage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;postgres:17"&lt;/span&gt;
  &lt;span class="na"&gt;postgresPassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;
  &lt;span class="na"&gt;localTest&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;false&lt;/span&gt;
  &lt;span class="na"&gt;rdsInstanceClass&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;db.t3.micro"&lt;/span&gt;
  &lt;span class="na"&gt;rdsAllocatedStorage&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;20&lt;/span&gt;
  &lt;span class="na"&gt;rdsEngineVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;17"&lt;/span&gt;
  &lt;span class="na"&gt;rdsDBName&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keycloak"&lt;/span&gt;
  &lt;span class="na"&gt;rdsUsername&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;keycloak"&lt;/span&gt;
  &lt;span class="na"&gt;rdsManageMasterUserPassword&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; 
  &lt;span class="na"&gt;rdsSubnetIDs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subnet-0436a5657992422d2"&lt;/span&gt;  &lt;span class="c1"&gt;# us-east-1a - CAMBIAR&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;subnet-03fc372cafad1feec"&lt;/span&gt;  &lt;span class="c1"&gt;# us-east-1b - CAMBIAR&lt;/span&gt;
  &lt;span class="na"&gt;rdsVPCID&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;vpc-0d7e4425ca4d23f89"&lt;/span&gt;  &lt;span class="c1"&gt;# CAMBIAR&lt;/span&gt;
  &lt;span class="na"&gt;rdsAllowedCIDRs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;10.0.0.0/16"&lt;/span&gt;  &lt;span class="c1"&gt;# CIDR de tu VPC&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apply the KeycloakStack yaml resource for deploy and test.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;kubectl apply -f sample/02-aws-rds-deploy.yaml 
keycloakstack.kro.run/keycloak-dev created
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Step 10.
&lt;/h3&gt;

&lt;p&gt;Validate that resources are ready.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="go"&gt;kubectl get keycloakstack,dbsubnetgroups,securitygroups,dbinstances,secretstore,externalsecret,secrets,svc,deployments,pods,ingress -n default

NAME                                 STATE    READY   AGE
keycloakstack.kro.run/keycloak-dev   ACTIVE   True    11m

NAME                                                           AGE
dbsubnetgroup.rds.services.k8s.aws/keycloak-subnet-group-dev   11m

NAME                                                     ID
securitygroup.ec2.services.k8s.aws/keycloak-rds-sg-dev   sg-0bae8ee9ebb07ac3b
securitygroup.ec2.services.k8s.aws/my-webserver-sg       sg-06db013ac4841cf58

NAME                                               STATUS
dbinstance.rds.services.k8s.aws/keycloak-rds-dev   available

NAME                                                  AGE   STATUS   CAPABILITIES   READY
secretstore.external-secrets.io/aws-secretstore-dev   11m   Valid    ReadWrite      True

NAME                                                       STORETYPE     STORE                 REFRESH INTERVAL   STATUS         READY
externalsecret.external-secrets.io/rds-password-sync-dev   SecretStore   aws-secretstore-dev   1h                 SecretSynced   True

NAME                             TYPE     DATA   AGE
secret/aws-credentials           Opaque   4      2m6s
secret/rds-connection-dev        Opaque   4      7m15s
secret/rds-password-synced-dev   Opaque   2      11m

NAME                           TYPE           CLUSTER-IP      EXTERNAL-IP                                                 PORT(S)    AGE
&lt;/span&gt;&lt;span class="gp"&gt;service/keycloak-service-dev   ClusterIP      10.102.50.198   &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;                                                      &lt;/span&gt;8080/TCP   11m
&lt;span class="gp"&gt;service/kubernetes             ClusterIP      10.96.0.1       &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;                                                      &lt;/span&gt;443/TCP    4d3h
&lt;span class="gp"&gt;service/postgres-service       ExternalName   &amp;lt;none&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;          &lt;/span&gt;keycloak-rds-dev.ckxssqysgxjv.us-east-1.rds.amazonaws.com   5432/TCP   7m15s
&lt;span class="go"&gt;
NAME                           READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/keycloak-dev   0/1     1            0           11m

NAME                                READY   STATUS    RESTARTS   AGE
pod/keycloak-dev-6fc5c4bdd9-kgkzf   1/1     Running   0          8m4s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Create a port forward and use keycloakHostname value, in this case "keycloakrds.local".&lt;br&gt;
&lt;a href="https://media2.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%2Ffc8s6lp9fb5aj2xiu0kd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffc8s6lp9fb5aj2xiu0kd.png" alt="k8s port forward k9s" width="800" height="227"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For connect con admin, the password is in the secret (rds-password-synced-dev). &lt;br&gt;
&lt;a href="https://media2.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%2F0f9o3kj2owifj127cnmh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0f9o3kj2owifj127cnmh.png" alt="Resource graph definition Keycloak api description" width="800" height="469"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CONCLUSION:
&lt;/h2&gt;

&lt;p&gt;The combination of AMDF and KIRO acts as a force multiplier, allowing us to build robust, validated, and reusable OCI packages or in this case Yaml manifests from existing CRDs faster.&lt;/p&gt;

&lt;p&gt;Using KCL instead of traditional YAML isn't just a syntax preference—it’s about building a safer, more modular, and maintainable for our Cloud Native ecosystem.&lt;/p&gt;

</description>
      <category>kcl</category>
      <category>cloudnative</category>
      <category>kubernetes</category>
      <category>mcp</category>
    </item>
    <item>
      <title>KCL For Managing Infraestructure as Data</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Wed, 03 Dec 2025 23:01:02 +0000</pubDate>
      <link>https://forem.com/segoja7/kcl-for-managing-infraestructure-as-data-n7a</link>
      <guid>https://forem.com/segoja7/kcl-for-managing-infraestructure-as-data-n7a</guid>
      <description>&lt;p&gt;In the previous &lt;a href="https://dev.to/segoja7/fast-overview-for-infraestructure-as-data-4bep"&gt;blog&lt;/a&gt; it's mentioned some benefits about of IaD and how this concept this wide used in cloud native, let me write in this post about KCL for create anything declarative manifest.&lt;/p&gt;

&lt;h2&gt;
  
  
  KCL
&lt;/h2&gt;

&lt;p&gt;KCL is an open source configuration and policy language, currently a Cloud Native Computing Foundation (CNCF) Sandbox project.&lt;/p&gt;

&lt;p&gt;It was created to overcome the limitations of static formats like YAML or JSON, especially in complex cloud-native environments. To achieve this, KCL combines the simplicity of a data language with the power of a modern programming language, allowing you to create abstractions, enforce validations through a constraint system, and automate large-scale data management.&lt;/p&gt;

&lt;p&gt;In short, you write in KCL to generate configurations for tools like Kubernetes and any tools that use yaml in a much safer, more scalable, and programmable way.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think in KCL like as high level language with a DevEx similar a Pyhton.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There is a fundamental concepts that I will omit, but if you have experience with other programing languages, you don't have problems with KCL foundations.&lt;/p&gt;

&lt;p&gt;If could be validate this concepts in this &lt;a href="https://www.kcl-lang.io/docs/reference/lang/spec/" rel="noopener noreferrer"&gt;official link&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  KCL Schemas
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Basic Schema
&lt;/h4&gt;

&lt;p&gt;schema is a blueprint that defines the structure of your configuration. It tells KCL exactly what attributes an object should have, what type they are, and what their default values are.&lt;/p&gt;

&lt;p&gt;Key points**&lt;br&gt;
Attribute Definition: Within a schema, each attribute must have a type (name: str, replica: int).&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Optional attributes (?) : If an attribute may not be present, you add a ? to its name (labels?: {str:str}). If you don't add, the attribute is mandatory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Default values (=): You can assign a default value to any attribute (replica: int = 1). If you do not specify a value when creating an instance, this value will be used.&lt;/p&gt;

&lt;p&gt;Create an Instance: You use the schema name followed by braces {} to create a concrete configuration from the blueprint.&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Schemas and Data Types
&lt;/h3&gt;

&lt;p&gt;The fundamental unit in KCL is the schema, which acts as a blueprint or template for your configuration. Within a schema, you define attributes with specific data types (str, bool, int) and can assign default values.&lt;/p&gt;

&lt;p&gt;Example: Basic application configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;schema eksCluster:
    clusterName: str
    encryptCluster: bool = True

# It's not necessary to specify 'EncryptCluster' if its default value is desired.
eksCluster {
    clusterName = "segoja7-cluster"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resulting YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clusterName: segoja7-cluster
encryptCluster: true
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Nested Schemas: Creating Structure
&lt;/h3&gt;

&lt;p&gt;To handle more complex configurations, a schema can use another schema as the type for one of its attributes. This creates a nested and organized structure, mirroring the hierarchy of the final YAML.&lt;/p&gt;

&lt;p&gt;Example: Adding a Node section.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;schema nodeCluster:
    diskSize : int
    ami: str


schema eksCluster:
    clusterName: str
    encryptCluster: bool = True
    nodeConfig: nodeCluster  # &amp;lt;-- Attribute whose type is another schema

eksCluster {
    clusterName = "segoja7-cluster"
    nodeConfig.diskSize = 20
    nodeConfig.ami = "BOTTLEROCKET_x86_64"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resulting YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clusterName: segoja7-cluster
encryptCluster: true
nodeConfig:
  diskSize: 20
  ami: BOTTLEROCKET_x86_64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Lists of Schemas: Handling Collections
&lt;/h3&gt;

&lt;p&gt;To define a list of complex objects, you use bracket syntax [] with the schema name (e.g., [MySchema]). This ensures that every element in the list conforms to the structure defined in the schema.&lt;/p&gt;

&lt;p&gt;Example: Adding a list of Tags.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;schema nodeCluster:
    diskSize : int
    ami: str

schema tags:
    key: str
    value: str 

schema eksCluster:
    clusterName: str
    encryptCluster: bool = True
    nodeConfig: nodeCluster  
    tags: [tags] # &amp;lt;-- Attribute whose type is a LIST of another 


eksCluster {
    clusterName = "segoja7-cluster"
    nodeConfig.diskSize = 20
    nodeConfig.ami = "BOTTLEROCKET_x86_64"
    tags = [
        { key = "Name", value = "NodeGroup" },
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Resulting YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clusterName: segoja7-cluster
encryptCluster: true
nodeConfig:
  diskSize: 20
  ami: BOTTLEROCKET_x86_64
tags:
- key: Name
  value: NodeGroup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  4. Schemas (Logic and Validation)
&lt;/h3&gt;

&lt;p&gt;This is where schemas become really powerful. They are not only data containers, they can also contain logic and validation rules.&lt;/p&gt;

&lt;p&gt;Schema arguments (schema MySchema[argument]: ) You can pass parameters to a schema that are not final attributes, but are used for internal logic.&lt;/p&gt;

&lt;p&gt;The check block: This block is the "quality inspector" of your schema. Inside it, you write a series of rules (asserts) that each schema instance must comply with. If any rule fails, KCL will stop the compilation with an error. This is much cleaner than having loose asserts in the file.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;schema nodeCluster:
    diskSize : int
    ami: str

schema tags:
    key: str
    value: str 

schema eksCluster[env: str]:
    clusterName: str
    encryptCluster: bool = False
    nodeConfig: nodeCluster  
    tags: [tags]
    check:
        encryptCluster != False if env == "prod", "Production cluster need to be encrypt"


eksCluster(env="prod") {
    clusterName = "segoja7-cluster"
    nodeConfig.diskSize = 20
    nodeConfig.ami = "BOTTLEROCKET_x86_64"
    tags = [
        { key = "Name", value = "NodeGroup" },
    ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output with encryptCluster = false and check using production env argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kcl run main.k 
EvaluationError
  --&amp;gt; /main.k:18:1
   |
18 | eksCluster(env="prod") {
   | ^ Instance check failed
   |

  --&amp;gt; /main.k:15:1
   |
15 |         encryptCluster != False if env == "prod", "Production cluster need to be encrypt"
   |  Check failed on the condition: Production cluster need to be encrypt
   |
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Output with encryptCluster = true and check using production env argument:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;clusterName: segoja7-cluster
encryptCluster: true
nodeConfig:
  diskSize: 20
  ami: BOTTLEROCKET_x86_64
tags:
- key: Name
  value: NodeGroup
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;Inheritance, protocol and Mixins
The Core Concepts: When to Use Each.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;The key is to identify the relationship between your schemas.&lt;/p&gt;

&lt;p&gt;Inheritance: Use inheritance when one schema is a more specialized version of another. It creates a clear parent-child hierarchy.&lt;/p&gt;

&lt;p&gt;protocol/Mixin: Use a protocol/mixin when you want to add a reusable packet of features to different, unrelated schemas.&lt;/p&gt;

&lt;p&gt;Protocol: Is a contract that defines a set of attributes that a schema must have in order to use a specific functionality.&lt;br&gt;
mixin: A mixin is a block of code containing attributes and logic that can be "mixed" or injected into a schema.&lt;br&gt;
The data flow is always: ➡️ Esquema ➡️ Mixin ➡️ Protocol.&lt;/p&gt;

&lt;p&gt;Example: Inheritance, protocol and Mixins.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;schema nodeCluster:
    diskSize : int
    ami: str

schema tags:
    key: str
    value: str 

schema eksCluster[env: str]:
    clusterName: str
    encryptCluster: bool = True
    nodeConfig: nodeCluster  
    tags: [tags]
    monitoring_logs?: [str] = []
    check:
        encryptCluster != False if env == "prod", "Production cluster need to be encrypt"

protocol monitoringProtocol: # &amp;lt;-- Protocol: contract for mixin with optional field enabledLogs
    enabledLogs?: bool

mixin monitoringMixin for monitoringProtocol: # &amp;lt;-- Mixin: adds monitoring monitoring_logs if enabledLogs is provided  
    if enabledLogs:
        monitoring_logs = [
            "api",
            "audit",
            "authenticator",
            "controllerManager",
            "scheduler",
        ]

schema eksClusterWithMonitoring[env: str](eksCluster): # &amp;lt;-- Inheritance
    mixin [monitoringMixin]
    enabledLogs: bool 

prod = eksClusterWithMonitoring(env="prod") { #Prod with logs
    clusterName = "segoja7-cluster"
    nodeConfig.diskSize = 20
    nodeConfig.ami = "BOTTLEROCKET_x86_64"
    tags = [
        { key = "Name", value = "NodeGroup" },
    ]
    enabledLogs = True
}

dev = eksCluster(env="dev"){ #Dev without logs
    clusterName = "segoja7-cluster"
    encryptCluster = False
    nodeConfig.diskSize = 20
    nodeConfig.ami = "BOTTLEROCKET_x86_64"
    tags = [
        { key = "Name", value = "NodeGroup" },
    ]   
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Final Resulting YAML:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;prod:
  clusterName: segoja7-cluster
  encryptCluster: true
  nodeConfig:
    diskSize: 20
    ami: BOTTLEROCKET_x86_64
  tags:
  - key: Name
    value: NodeGroup
  monitoring_logs:
  - api
  - audit
  - authenticator
  - controllerManager
  - scheduler
  enabledLogs: true
dev:
  clusterName: segoja7-cluster
  encryptCluster: false
  nodeConfig:
    diskSize: 20
    ami: BOTTLEROCKET_x86_64
  tags:
  - key: Name
    value: NodeGroup
  monitoring_logs: []
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  CONCLUSION:
&lt;/h3&gt;

&lt;p&gt;KCl is a language with features like as another high level programing language with a DevEx similar to Python, KCL create declarative manifests that all tools from cloud-native systems understand. With KCL we can introduce abstraction, early validation and modularity enabling platform teams to scale their operations safely and efficiently.&lt;/p&gt;

</description>
      <category>kcl</category>
      <category>cloudnative</category>
      <category>kubernetes</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Fast Overview for Infraestructure as Data</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Fri, 07 Nov 2025 17:52:41 +0000</pubDate>
      <link>https://forem.com/segoja7/fast-overview-for-infraestructure-as-data-4bep</link>
      <guid>https://forem.com/segoja7/fast-overview-for-infraestructure-as-data-4bep</guid>
      <description>&lt;h2&gt;
  
  
  Infrastructure as Data (IaD)
&lt;/h2&gt;

&lt;p&gt;Infrastructure as Data (IaD) is basically about defining your infrastructure using structured data files—stuff like YAML or JSON—instead of traditional scripts or config languages that mix in programming logic. No code, just data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Think of it as an evolution or a tighter subset of "Infrastructure as Code" (IaC). While IaC encompasses any method for managing infrastructure through code, IaD focuses on a purely declarative model. &lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In another words you declare the desire state of your declarative manifests then let automation systems work. They’ll constantly check and enforce that what’s running matches what you described.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;IaD was created to solve this problem through its main mechanism: the reconciliation loop.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  The Reconciliation Loop
&lt;/h3&gt;

&lt;p&gt;IaD is primarily implemented in the Kubernetes ecosystem, using its API as a universal control plane.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Definition as Data&lt;/strong&gt;: You define a cloud resource (a database, a bucket, a network) in a YAML file, as if it were a Kubernetes object.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Active Controllers&lt;/strong&gt;: Tools such as Crossplane, Config Connector (GCP) or ACK (AWS) install "Controllers" in your cluster.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Continuous Reconciliation&lt;/strong&gt;: These drivers constantly observe two things: the desired state (your YAML file) and the actual state (in the cloud). If they detect a difference, they automatically take action to bring reality back to match the definition. This loop is perpetual.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This model ensures that any manual changes are reverted, keeping the infrastructure in sync with your Git statement at all times.&lt;/p&gt;

&lt;h3&gt;
  
  
  Problem Solving: The Limitations of IaC  (configuration drift).
&lt;/h3&gt;

&lt;p&gt;Example: If a Engineer make a change of a resource directly in the console for any reason, IaC tools doesn't have the capacity for detect that change, this require an manual execution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Key Benefits of IaD
&lt;/h2&gt;

&lt;p&gt;Infrastructure as Data (IaD) marks a advancement in how we manage infrastructure, particularly when compared to traditional Infrastructure as Code (IaC) methods. In cloud-native and GitOps contexts, the impact of IaD becomes even more apparent.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Elimination of Configuration Drift:&lt;/strong&gt; IaD ensures that the actual state of the infrastructure always matches the definition in Git.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Desired states&lt;/strong&gt;: By leaving out logic, no loops or conditionals in the definition files and focusing only on data, the deployment process becomes much more transparent.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cognitive Load Reduction&lt;/strong&gt;: The learning curve and cognitive load for teams already running Kubernetes is reduced,  pure YAML/JSON files are inherently easier to read and write.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Permissions Model&lt;/strong&gt;: Developers or application teams can "request" (claim) standardized infrastructure (ej. "Database") without having direct credentials in the cloud.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Centralization of Security&lt;/strong&gt;: Platform teams can encapsulate security, compliance and governance best practices within the abstract resource definitions, ensuring that all provisioned infrastructure complies with the organization's policies.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Traceability&lt;/strong&gt;: All definitions are in Git and changes are applied through an automated system, you get a complete and clear audit trail of all infrastructure changes.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Automation&lt;/strong&gt;: It aligns perfectly with the GitOps methodology, where any infrastructure change is initiated with a git push, which automates the entire lifecycle.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Modularity and Reusability&lt;/strong&gt;: It can be created and destroyed with complete confidence and reproducibility, &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  IaD Tools
&lt;/h2&gt;

&lt;p&gt;This a ecosystem of Infrastructure as Data (IaD) tools that complement each other to leverage this philosophy to the maximum.&lt;/p&gt;

&lt;p&gt;The key is that these tools focus on defining resources as declarative data and/or use a reconciliation loop to maintain state.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Infrastructure Abstraction and Control Plane (IaD Core)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href="https://docs.crossplane.io/v2.0/" rel="noopener noreferrer"&gt;Crossplane&lt;/a&gt; Agnostic any cloud provider.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/config-connector/docs/overview" rel="noopener noreferrer"&gt;Config Connector (GCP)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://aws-controllers-k8s.github.io/community/" rel="noopener noreferrer"&gt;AWS Controllers for Kubernetes (ACK)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://azure.github.io/azure-service-operator/" rel="noopener noreferrer"&gt;Azure Service Operator (ASO)&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kro.run/docs/overview/" rel="noopener noreferrer"&gt;KRO&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Continuous Delivery (GitOps) for IaD
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://argo-cd.readthedocs.io/en/stable/" rel="noopener noreferrer"&gt;Argo CD&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://fluxcd.io/" rel="noopener noreferrer"&gt;Flux CD&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. Configuration and Customization Management (IaD Support)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kustomize.io/" rel="noopener noreferrer"&gt;Kustomize&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://helm.sh/" rel="noopener noreferrer"&gt;HELM&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kcl-lang.io/" rel="noopener noreferrer"&gt;KCL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  4. Policy and Governance (IaD Policy)
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://kyverno.io/" rel="noopener noreferrer"&gt;Kyverno&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kcl-lang.io/" rel="noopener noreferrer"&gt;KCL&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.openpolicyagent.org/" rel="noopener noreferrer"&gt;OPA&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  5. Others tools and will continue ...
&lt;/h3&gt;

&lt;h3&gt;
  
  
  CONCLUSION
&lt;/h3&gt;

&lt;p&gt;IaD is not just a different way of writing infrastructure, it is a philosophy that boosts reliability, security and agility in cloud infrastructure management by leveraging declarative principles and control loops to maintain the desired state in a continuous and automated manner.&lt;/p&gt;

</description>
      <category>kcl</category>
      <category>cloudnative</category>
      <category>kubernetes</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Hands-on Lab #1: Creating Crossplane v1.20 Configuration Packages for Keycloak on AWS</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Wed, 09 Jul 2025 20:37:05 +0000</pubDate>
      <link>https://forem.com/segoja7/platform-engineering-hands-on-lab-1-creating-crossplane-configuration-packages-for-keycloak-on-aws-boe</link>
      <guid>https://forem.com/segoja7/platform-engineering-hands-on-lab-1-creating-crossplane-configuration-packages-for-keycloak-on-aws-boe</guid>
      <description>&lt;h2&gt;
  
  
  What are Crossplane Configuration Packages?
&lt;/h2&gt;

&lt;p&gt;Crossplane Configuration Packages are the high level of infrastructure reusability in the Crossplane ecosystem. Think of Crossplane Configuration Packages like Docker images for infrastructure. The configurations allow generated distributable packages that can be deployed consistently any environments.&lt;/p&gt;

&lt;p&gt;So, for create configurations package is necessary create compositions and compositions resource definitions (xrd), if you have any doubts about these concepts, check this blog. &lt;/p&gt;
&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap" class="crayons-story__hidden-navigation-link"&gt;KCL Function+ Crossplane: A Declarative Language for Deploying Complex Infrastructure on AWS with Kubernetes.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/segoja7" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" alt="segoja7 profile" class="crayons-avatar__image"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/segoja7" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Javier Sepúlveda
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Javier Sepúlveda
                
              
              &lt;div id="story-author-preview-content-2079943" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/segoja7" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" class="crayons-avatar__image" alt=""&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Javier Sepúlveda&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Nov 19 '24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap" id="article-link-2079943"&gt;
          KCL Function+ Crossplane: A Declarative Language for Deploying Complex Infrastructure on AWS with Kubernetes.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/kubernetes"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;kubernetes&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/crossplane"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;crossplane&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/iac"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;iac&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="18" height="18"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;6&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            5 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;h2&gt;
  
  
  Requirements for local test
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster (&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Helm version v3.13.1 or later&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.crossplane.io/latest/software/install/" rel="noopener noreferrer"&gt;Crossplane&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;programmatic access AWS&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.crossplane.io/latest/cli/" rel="noopener noreferrer"&gt;Crossplane CLI&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Link Repositoy
&lt;/h3&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/configuration-crossplane-keycloak" rel="noopener noreferrer"&gt;
        configuration-crossplane-keycloak
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This a repository for crossplane configuration package keycloak in AWS
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Project Overview&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;This is a Crossplane-based infrastructure-as-code project that deploys a comprehensive AWS EKS cluster with associated infrastructure using KCL. The project creates a multi-AZ infrastructure including VPC, subnets, EKS cluster, RDS database, and various controllers.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Architecture&lt;/h2&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Core Components&lt;/h3&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Crossplane Configuration&lt;/strong&gt;: Manages AWS infrastructure through Crossplane providers&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;KCL Functions&lt;/strong&gt;: KCL for infrastructure composition&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;AWS Resources&lt;/strong&gt;: Creates VPC, EKS cluster, RDS, security groups, IAM roles, and networking components&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Helm Charts&lt;/strong&gt;: Deploys cert-manager, AWS Load Balancer Controller, ingress-nginx, and external-dns&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Kubernetes Objetcs&lt;/strong&gt;: Deploys objects of kubernets such as Deployments, services, ingress and others&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Key Files&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;resources/compositions/infra/composition.k&lt;/code&gt;: Main KCL composition defining all AWS resources&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resources/compositions/infra/crd.k&lt;/code&gt;: Custom Resource Definition for the infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resources/examples/claim.yaml&lt;/code&gt;: Example claim to provision infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configuration/crossplane.yaml&lt;/code&gt;: Crossplane configuration metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configuration/apis/infra/composition.yaml&lt;/code&gt;: Render from resources/compositions/infra/composition.k &amp;gt; any change is overwrite&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configuration/apis/infra/crd.yaml&lt;/code&gt;: Render from resources/compositions/infra/crd.k&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;function.yaml&lt;/code&gt;: Crossplane functions (KCL and auto-ready)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;provider.yaml&lt;/code&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/segoja7/configuration-crossplane-keycloak" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;
 
&lt;h3&gt;
  
  
  Key Files
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;resources/compositions/infra/composition.k&lt;/code&gt;: Main KCL composition defining all AWS resources&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resources/compositions/infra/crd.k&lt;/code&gt;: Custom Resource Definition for the infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;resources/examples/claim.yaml&lt;/code&gt;: Example claim to provision infrastructure&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configuration/crossplane.yaml&lt;/code&gt;: Crossplane configuration metadata&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configuration/apis/infra/composition.yaml&lt;/code&gt;: Render from resources/compositions/infra/composition.k&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;configuration/apis/infra/crd.yaml&lt;/code&gt;: Render from resources/compositions/infra/crd.k&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;function.yaml&lt;/code&gt;: Crossplane functions (KCL and auto-ready)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;install-configuration.yaml&lt;/code&gt;: Crossplane configuration metadata for install configuration package in the cluster.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;provider.yaml&lt;/code&gt;: AWS, Kubernetes and helm providers&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;providerconfig.yaml&lt;/code&gt;: Provider configuration&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Architecture.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F0j7kotnflmryg95sv104.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0j7kotnflmryg95sv104.png" alt="Keycloak basic architecture"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;First, create a profile in minikube&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start -p crossplane
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With minikube running is moment for install Helm and crossplane, check this &lt;a href="https://docs.crossplane.io/latest/software/install/" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;with the profile of minikube created and helm and crossplane running it is needed to create a txt file, for this case the document name is profile.txt&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
aws_access_key_id = &amp;lt;Your access key id&amp;gt;
aws_secret_access_key = &amp;lt;Your secret access key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;when the txt file is created it is necessary created a generic secret.&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 aws-secret -n crossplane-system --from-file=creds=./profile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;Install functions.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;The configuration have dependencies from this functions.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f function.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;p&gt;Installing a provider, in this case providers for aws, kubernetes and helm from community.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f provider.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4.
&lt;/h2&gt;

&lt;p&gt;Install providersconfig, it is using the key from secret with the name creds.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f providerconfig.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5.
&lt;/h2&gt;

&lt;p&gt;login in gihutb ghcr.io for push packages.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;echo "&amp;lt;github token&amp;gt;" | docker login ghcr.io -u &amp;lt;user&amp;gt; --password-stdin
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 6.
&lt;/h2&gt;

&lt;p&gt;Create Gihub Secret in the cluster for pull packages from github and install configuration package.&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 docker-registry ghcr-secret \
    --docker-server=ghcr.io \
    --docker-username=&amp;lt;username&amp;gt;\
    --docker-password=&amp;lt;token&amp;gt; \
    -n crossplane-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 7.
&lt;/h2&gt;

&lt;p&gt;Render compositions and XRD&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;These files are the result of the composition and crd created using kcl, any changes should be made from the .k files.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kcl run resources/compositions/infra/crd.k &amp;gt; configuration/apis/crd.yaml
kcl run resources/compositions/infra/composition.k &amp;gt; configuration/apis/composition.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 8.
&lt;/h2&gt;

&lt;p&gt;Build package configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crossplane xpkg build --package-root=./configuration/ --package-file=segoja7-configuration-keycloack.xpkg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 9.
&lt;/h2&gt;

&lt;p&gt;Push package configuration in the github account.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;crossplane xpkg push ghcr.io/segoja7/segoja7-configuration-keycloack:v1.0.0 -f segoja7-configuration-keycloack.xpkg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 10.
&lt;/h2&gt;

&lt;p&gt;Install-configuration.yaml allow install the configuration package in the cluster using the secret for authenticated and pull the OCI package configuration.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ kubectl apply -f install-configuration.yaml
configuration.pkg.crossplane.io/segoja7-configuration-keycloack created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 11.
&lt;/h2&gt;

&lt;p&gt;Apply Claim is the end step, basically is create all resources abstracted and wait for her (status = True) for make probes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ kubectl apply -f resources/examples/claim.yaml
multiazinfraclaim.segoja7.example/infra-claim created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 12.
&lt;/h2&gt;

&lt;p&gt;Verify all resources created.&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 configuration.pkg
NAME                              INSTALLED   HEALTHY   PACKAGE                                                  AGE
segoja7-configuration-keycloack   True        True      ghcr.io/segoja7/segoja7-configuration-keycloack:v1.0.0   3h15m
➜ kubectl get compositions
NAME                XR-KIND         XR-APIVERSION              AGE
infra-composition   XMultiAzInfra   segoja7.example/v1alpha1   3h15m
&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;➜ kubectl get managed
Warning: BucketPolicy has been deprecated. Use spec.forProvider.policy in Bucket instead.
NAME                                                                  READY   SYNCED   AGE
dbsubnetgroup.database.aws.crossplane.io/backstage-subnet-group-idp   True    True     173m

NAME                                                       READY   SYNCED   STATE       ENGINE     VERSION   AGE
rdsinstance.database.aws.crossplane.io/storedata-rds-idp   True    True     available   postgres   17.4      173m

NAME                                    READY   SYNCED   ID                           IP              AGE
address.ec2.aws.crossplane.io/eip-idp   True    True     eipalloc-084d47829c9883e7f   54.146.16.193   173m

NAME                                            READY   SYNCED   ID                      VPC                     AGE
internetgateway.ec2.aws.crossplane.io/igw-idp   True    True     igw-0070a8d25d170cd90   vpc-0194aa72b31ff1d10   173m

NAME                                      READY   SYNCED   ID                      VPC                     SUBNET                     ALLOCATION ID                AGE
natgateway.ec2.aws.crossplane.io/ng-idp   True    True     nat-023fe7472e37f1f37   vpc-0194aa72b31ff1d10   subnet-026e050150dc85f90   eipalloc-084d47829c9883e7f   173m

NAME                                              READY   SYNCED   ID                      VPC                     AGE
routetable.ec2.aws.crossplane.io/rt-private-idp   True    True     rtb-0b62322c0b2315bd6   vpc-0194aa72b31ff1d10   173m
routetable.ec2.aws.crossplane.io/rt-public-idp    True    True     rtb-0aedc83d1aed5cdca   vpc-0194aa72b31ff1d10   173m

NAME                                                       READY   SYNCED   ID                     VPC                     AGE
securitygroup.ec2.aws.crossplane.io/backstage-rds-sg-idp   True    True     sg-071aed1f2a6d58405   vpc-0194aa72b31ff1d10   173m

NAME                                                       READY   SYNCED   ID                         VPC                     CIDR            AGE
subnet.ec2.aws.crossplane.io/app-private-subnet-az1-idp    True    True     subnet-0a5e735e87bccc368   vpc-0194aa72b31ff1d10   172.16.3.0/24   173m
subnet.ec2.aws.crossplane.io/app-private-subnet-az2-idp    True    True     subnet-09b23d56234e463fe   vpc-0194aa72b31ff1d10   172.16.4.0/24   173m
subnet.ec2.aws.crossplane.io/data-private-subnet-az1-idp   True    True     subnet-07be7b51481002165   vpc-0194aa72b31ff1d10   172.16.1.0/24   173m
subnet.ec2.aws.crossplane.io/data-private-subnet-az2-idp   True    True     subnet-0407ee651c0c58509   vpc-0194aa72b31ff1d10   172.16.2.0/24   173m
subnet.ec2.aws.crossplane.io/public-subnet-az1-idp         True    True     subnet-026e050150dc85f90   vpc-0194aa72b31ff1d10   172.16.5.0/24   173m
subnet.ec2.aws.crossplane.io/public-subnet-az2-idp         True    True     subnet-06404627395c08051   vpc-0194aa72b31ff1d10   172.16.6.0/24   173m

NAME                                READY   SYNCED   ID                      CIDR            IPV6CIDR   AGE
vpc.ec2.aws.crossplane.io/vpc-idp   True    True     vpc-0194aa72b31ff1d10   172.16.0.0/16              173m

NAME                                        READY   SYNCED   AGE
cluster.eks.aws.crossplane.io/cluster-idp   True    True     173m

NAME                                                           READY   SYNCED   EXTERNAL-NAME                                                                                                      AGE
addon.eks.aws.crossplane.io/addon-coredns-idp                  True    True     arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/coredns/4ccbf7c3-52dd-d8ca-bf02-ccdf71f63fae                  173m        
addon.eks.aws.crossplane.io/addon-eks-pod-identity-agent-idp   True    True     arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/eks-pod-identity-agent/c6cbf7c3-7123-3fae-d85d-bf0def5f9222   173m        
addon.eks.aws.crossplane.io/addon-kube-proxy-idp               True    True     arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/kube-proxy/a8cbf7c3-537e-5279-faba-1c655083254d               173m        
addon.eks.aws.crossplane.io/addon-vpc-cni-idp                  True    True     arn:aws:eks:us-east-1:476114125818:addon/cluster-idp/vpc-cni/40cbf7c3-7117-f2a4-05db-9fd138a12831                  173m        

NAME                                            READY   SYNCED   CLUSTER       AGE
nodegroup.eks.aws.crossplane.io/nodegroup-idp   True    True     cluster-idp   173m

NAME                                                          CHART                          VERSION   SYNCED   READY   STATE      REVISION   DESCRIPTION        AGE
release.helm.crossplane.io/aws-load-balancer-controller-idp   aws-load-balancer-controller   1.13.3    True     True    deployed   152        Upgrade complete   173m
release.helm.crossplane.io/cert-manageridp                    cert-manager                   v1.18.2   True     False                                            173m
release.helm.crossplane.io/external-dnsidp                    external-dns                   1.17.0    True     True    deployed   155        Upgrade complete   173m
release.helm.crossplane.io/ingress-nginxidp                   ingress-nginx                  4.12.2    True     True    deployed   1          Install complete   173m

NAME                                                         READY   SYNCED   URL
openidconnectprovider.iam.aws.crossplane.io/eks-openid-idp   True    True     https://oidc.eks.us-east-1.amazonaws.com/id/C9C33D016B220174E50834BA11189416

NAME                                                          ARN                                                               READY   SYNCED   AGE
policy.iam.aws.crossplane.io/awsloadbalancer-controller-idp   arn:aws:iam::476114125818:policy/awsloadbalancer-controller-idp   True    True     173m
policy.iam.aws.crossplane.io/external-dns-idp                 arn:aws:iam::476114125818:policy/external-dns-idp                 True    True     173m

NAME                                                                                  READY   SYNCED   ROLENAME                            POLICYARN                                                         AGE
rolepolicyattachment.iam.aws.crossplane.io/clusteradminrolepolicy-idp                 True    True     clusteradminrole-idp                arn:aws:iam::aws:policy/AdministratorAccess                       173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-1                True    True     clusternoderole-idp                 arn:aws:iam::aws:policy/AmazonEKSWorkerNodePolicy                 173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-2                True    True     clusternoderole-idp                 arn:aws:iam::aws:policy/AmazonEKS_CNI_Policy                      173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-3                True    True     clusternoderole-idp                 arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryReadOnly        173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-4                True    True     clusternoderole-idp                 arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore              173m
rolepolicyattachment.iam.aws.crossplane.io/clusternoderolepolicy-idp-5                True    True     clusternoderole-idp                 arn:aws:iam::aws:policy/AmazonEC2ContainerRegistryPullOnly        173m
rolepolicyattachment.iam.aws.crossplane.io/clusterrolepolicy-idp                      True    True     clusterrole-idp                     arn:aws:iam::aws:policy/AmazonEKSClusterPolicy                    173m
rolepolicyattachment.iam.aws.crossplane.io/sa-awsloadbalancer-controller-policy-idp   True    True     sa-awsloadbalancer-controller-idp   arn:aws:iam::476114125818:policy/awsloadbalancer-controller-idp   173m
rolepolicyattachment.iam.aws.crossplane.io/sa-cert-manager-policy-idp                 True    True     sa-cert-manager-idp                 arn:aws:iam::aws:policy/AmazonRoute53FullAccess                   173m
rolepolicyattachment.iam.aws.crossplane.io/sa-external-dns-policy-idp                 True    True     sa-external-dns-idp                 arn:aws:iam::476114125818:policy/external-dns-idp                 173m

NAME                                                           ARN                                                                READY   SYNCED   AGE
role.iam.aws.crossplane.io/clusteradminrole-idp                arn:aws:iam::476114125818:role/clusteradminrole-idp                True    True     173m
role.iam.aws.crossplane.io/clusternoderole-idp                 arn:aws:iam::476114125818:role/clusternoderole-idp                 True    True     173m
role.iam.aws.crossplane.io/clusterrole-idp                     arn:aws:iam::476114125818:role/clusterrole-idp                     True    True     173m
role.iam.aws.crossplane.io/sa-awsloadbalancer-controller-idp   arn:aws:iam::476114125818:role/sa-awsloadbalancer-controller-idp   True    True     173m
role.iam.aws.crossplane.io/sa-cert-manager-idp                 arn:aws:iam::476114125818:role/sa-cert-manager-idp                 True    True     173m
role.iam.aws.crossplane.io/sa-external-dns-idp                 arn:aws:iam::476114125818:role/sa-external-dns-idp                 True    True     173m

NAME                                                             KIND            PROVIDERCONFIG     SYNCED   READY   AGE
object.kubernetes.crossplane.io/cert-manager-certificate-idp     Certificate     provider-k8s-idp   True     True    173m
object.kubernetes.crossplane.io/cert-manager-clusterissuer-idp   ClusterIssuer   provider-k8s-idp   True     True    173m
object.kubernetes.crossplane.io/k8s-secret-idp                   Secret          provider-k8s-idp   True     True    173m
object.kubernetes.crossplane.io/keycloak-deployment-idp          Deployment      provider-k8s-idp   True     True    173m
object.kubernetes.crossplane.io/keycloak-ingress-idp             Ingress         provider-k8s-idp   True     True    173m
object.kubernetes.crossplane.io/keycloak-service-idp             Service         provider-k8s-idp   True     True    173m
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  TESTING URL FOR KEYCLOAK
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbazn1d5k50hi32rquugj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbazn1d5k50hi32rquugj.png" alt="Keycloak url"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  ROUTE 53 Configuration from external-DNS
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2q9kn03temnyia3l565u.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2q9kn03temnyia3l565u.png" alt="external-DNS"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  CERTIFICATE FROM CERT-MANAGER
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fyayuviywx8ghu5ds1wjc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fyayuviywx8ghu5ds1wjc.png" alt="CERT-MANAGER"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 13.
&lt;/h2&gt;

&lt;p&gt;key points the claim&lt;/p&gt;

&lt;p&gt;The claim receive the following important parameters:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;hostedZoneID: Is a hostzoneID created for route53, is used for cert-manager and external-dns.&lt;/li&gt;
&lt;li&gt;keycloakHostname: "idp.segoja7.com" You need to change this parameter for a different url.&lt;/li&gt;
&lt;li&gt;domainNames: Is a list for create certificates and use in the keycloack deployment or ingress controller.
&amp;gt; Note: The configuration package create rds secret in the eks cluster, additional the password rds is the same for keycloack admin password.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;CONCLUSION:&lt;br&gt;
The configuration packages are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Composable: Combine multiple cloud resources into higher-level abstractions&lt;/li&gt;
&lt;li&gt;Reusable: Package once, deploy many times across teams and environments&lt;/li&gt;
&lt;li&gt;Versionable: Semantic versioning for infrastructure components&lt;/li&gt;
&lt;li&gt;Distributable: Share via OCI registries, just like container images.&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>identity</category>
      <category>aws</category>
      <category>keycloak</category>
      <category>platformengineering</category>
    </item>
    <item>
      <title>Creating APIS with AWS Controllers for Kubernetes (ACK) and Kube Resource Orchestrator(KRO) using KCL.</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Mon, 10 Feb 2025 18:25:24 +0000</pubDate>
      <link>https://forem.com/segoja7/creating-apis-with-aws-controllers-for-kubernetes-ack-and-kube-resource-orchestratorkro-using-3hb0</link>
      <guid>https://forem.com/segoja7/creating-apis-with-aws-controllers-for-kubernetes-ack-and-kube-resource-orchestratorkro-using-3hb0</guid>
      <description>&lt;p&gt;In November 2024 AWS announces and releases Kro as an opensource tool to simplify the use and creation of Custom APIs in Kubernetes and on January 30, 2025 google publishes on its &lt;a href="https://cloud.google.com/blog/products/containers-kubernetes/introducing-kube-resource-orchestrator" rel="noopener noreferrer"&gt;blog&lt;/a&gt; a collaboration between Azure, GCP and AWS for the development of this tool, at the moment Kro is experimental and is working to make kro ready for production.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is Kro?
&lt;/h1&gt;

&lt;p&gt;Kro is a native tool and agonostic cloud, is way to define and groupings applications and their dependencies encapsulating all this as a single resource that can be easily used by end users.&lt;/p&gt;

&lt;h1&gt;
  
  
  What is ACK?
&lt;/h1&gt;

&lt;p&gt;ACK are controllers for define and use AWS service resources directly from Kubernetes, check this &lt;a href="https://dev.to/segoja7/creating-infraestructure-with-the-ack-from-k8s-4dli"&gt;introduction blog&lt;/a&gt; with an basic example using ACK in EKS. &lt;/p&gt;

&lt;h1&gt;
  
  
  What is KCL?
&lt;/h1&gt;

&lt;p&gt;KCL is a configuration language that let us integrated Programming language techniques, in this blog Kcl is used for generated kubernetes manifests and reducing limitations of managing YAML configurations.&lt;/p&gt;

&lt;p&gt;Later of a short introduction,  it is time to deploy an application using ack controllers to deploy resources on AWS packaging all dependencies with Kro and using KCL to generate kubernetes manifests with more ease, order, control and reducing code repetition (DRY).&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster (&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;programmatic access AWS&lt;/li&gt;
&lt;li&gt;Helm version v3.16.2 or later&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kcl-lang.io/docs/user_docs/getting-started/install" rel="noopener noreferrer"&gt;KCL&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please check all code from this blog in this repository&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/kro_ack_k8s" rel="noopener noreferrer"&gt;
        kro_ack_k8s
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is an example integrating kro and ack controllers using minikube
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="MD"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;Kubernetes Deployments Simplified with Kro, ACK, and KCL&lt;/h1&gt;
&lt;/div&gt;
&lt;p&gt;This repository demonstrates how to deploy an application on AWS EKS using Kro, ACK controllers, and KCL. This powerful combination simplifies infrastructure management, reduces code duplication, and streamlines the deployment process.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Key Technologies&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Kro:&lt;/strong&gt; A cloud-agnostic, Kubernetes-native tool for defining and grouping applications and their dependencies.  Kro simplifies application management by encapsulating components as a single resource.  (Currently experimental and under active development.  See the &lt;strong&gt;Kro Status Update&lt;/strong&gt; below.)&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ACK (AWS Controllers for Kubernetes):&lt;/strong&gt;  Manage AWS service resources directly from your Kubernetes cluster.  ACK provides a bridge between your Kubernetes environment and various AWS services.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;KCL (Kubernetes Configuration Language):&lt;/strong&gt;  A modern configuration language that leverages programming language techniques to generate Kubernetes manifests. KCL promotes DRY (Don't Repeat Yourself) principles and reduces the complexity of managing YAML files.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;Kro Status Update&lt;/h2&gt;
&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Open Source Release (November 2024):&lt;/strong&gt; Kro is now open-source!&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cross-Cloud Collaboration (January&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/segoja7/kro_ack_k8s" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;All examples are divided in 2 sections&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Infra resources are in the path ./infra&lt;br&gt;
deploy resources are in the path ./deploy&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;Creating minikube profile.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start -p kro
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fcpulgs2b44o4xafn1bml.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fcpulgs2b44o4xafn1bml.png" alt="minikube profile" width="800" height="136"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;Installing KRO.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export KRO_VERSION=$(curl -sL \
    https://api.github.com/repos/kro-run/kro/releases/latest | \
    jq -r '.tag_name | ltrimstr("v")'
  )

helm install kro oci://ghcr.io/kro-run/kro/kro \
  --namespace kro \
  --create-namespace \
  --version=${KRO_VERSION}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2F6z0atlz9rkqdn4ap5via.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F6z0atlz9rkqdn4ap5via.png" alt="install kro" width="800" height="238"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Installing ACK Controllers.
&lt;/h3&gt;

&lt;p&gt;Creating new namespace for ACK.&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 ns ack-system
namespace/ack-system created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the namespace created is necessary defined an profile of AWS for create the resources, in this case an profile.txt is used for create after an secret in the namespace created.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;➜ cat ~/kro/profile.txt
[default]
aws_access_key_id = &amp;lt;access_key_id&amp;gt;
aws_secret_access_key = &amp;lt;secret_access_key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Note: This profile is used in a experimental and basic example, in another scenario IRSA is recommended&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create secret generic aws-credentials -n ack-system --from-file=credentials=/home/segoja7/kro/profile.txt
secret/aws-credentials created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Install ACK Controllers&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;CONTROLLER_REGION=us-east-1; \
SERVICES=("iam" "ec2" "eks"); \
for SERVICE in "${SERVICES[@]}"; do \
  RELEASE_VERSION=$(curl -sL https://api.github.com/repos/aws-controllers-k8s/${SERVICE}-controller/releases/latest | jq -r '.tag_name | ltrimstr("v")'); \
  if [[ -z "$RELEASE_VERSION" ]]; then \
    echo "Error: Could not retrieve release version for ${SERVICE}."; \
    continue; \
  fi; \
  helm install --create-namespace -n ack-system \
    oci://public.ecr.aws/aws-controllers-k8s/${SERVICE}-chart \
    --version="${RELEASE_VERSION}" \
    --generate-name \
    --set aws.region="${CONTROLLER_REGION}" \
    --set aws.credentials.secretName=aws-credentials \
    --set aws.credentials.profile=default; \
  if [[ $? -eq 0 ]]; then \
    echo "Successfully installed ${SERVICE} controller."; \
  else \
    echo "Error: Failed to install ${SERVICE} controller."; \
  fi; \
done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Creating an ResourceGraphDefinition for Infrastructure
&lt;/h3&gt;

&lt;p&gt;KCL is used to applied for defined on only resource and evit duplicate code.&lt;/p&gt;

&lt;p&gt;In an scenario normal is necessary defined multiples times the same resource.&lt;br&gt;
For example: validate this example in ACK page. &lt;a href="https://aws-controllers-k8s.github.io/community/docs/tutorials/ec2-example/#:~:text=%2D%2D%2D%0AapiVersion%3A%20ec2.services.k8s.aws/v1alpha1%0Akind%3A%20Subnet,tutorial%2Dvpc%0A%20%20routeTableRefs%3A%0A%20%20%2D%20from%3A%0A%20%20%20%20%20%20name%3A%20tutorial%2Dprivate%2Droute%2Dtable%2Daz1" rel="noopener noreferrer"&gt;link&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;with KCL it is possible to apply a logic to create in this case the subnets and associate them with their correct routetable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;    resources += [{    
        id = subnet_config.name
        template = {
            apiVersion = "ec2.services.k8s.aws/v1alpha1"
            kind = "Subnet"
            metadata = {
                name = subnet_config.name + my_config.project_name
            }
            spec = {
                availabilityZone = subnet_config.zone
                cidrBlock = subnet_config.cidr
                vpcID = r"""${vpc.status.vpcID}"""
                if subnet_config.type == "public":
                    mapPublicIPOnLaunch = True 
                    routeTables = [
                        r"""${routetablepublic.status.routeTableID}""" 
                    ]
                    tags = [
                        {
                            key = "ManagedBy"
                            value = apiVersion
                        }
                        {
                            key = "Name"
                            value = metadata.name
                        }
                        {
                            key = "kubernetes.io/role/elb" 
                            value = "1"
                        }
                        {
                            key = r"""kubernetes.io/cluster/cluster""" + my_config.project_name + """"""
                            value = "shared"
                        }
                    ]
                else:
                    mapPublicIPOnLaunch = False
                    routeTables = [
                        r"""${routetableprivate.status.routeTableID}"""
                    ]
                    tags = [
                        {
                            key = "ManagedBy"
                            value = apiVersion
                        }
                        {
                            key = "Name"
                            value = metadata.name
                        }
                        {
                            key = "kubernetes.io/role/internal-elb"
                            value = "1"
                        }
                        {
                            key = r"""kubernetes.io/cluster/cluster""" + my_config.project_name + """"""
                            value = "shared"
                        }
                    ]
            }
        }
    } for subnet_config in my_config.subnet_configs]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Aplying Infra ResourceGraphDefinition
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kcl infra-sample-app-stack.k | kubectl apply -f -
resourcegraphdefinition.kro.run/infrasampleappstack.kro.run created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case all infrastructure resources are packaged in a Custom Resource Definition called infrasampleappstacks with a KIND &lt;strong&gt;&lt;em&gt;InfraSampleAppStack&lt;/em&gt;&lt;/strong&gt; ready to be instantiated by an end user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F7ee2tpna7fqu7nq7m364.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F7ee2tpna7fqu7nq7m364.png" alt="kro infrasampleappstacks " width="800" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What resources are created:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;vpc&lt;/li&gt;
&lt;li&gt;internetgateway&lt;/li&gt;
&lt;li&gt;routetablepublic&lt;/li&gt;
&lt;li&gt;elasticipaddress&lt;/li&gt;
&lt;li&gt;clusterrole&lt;/li&gt;
&lt;li&gt;clusternoderole&lt;/li&gt;
&lt;li&gt;clusteradminrole&lt;/li&gt;
&lt;li&gt;publicsubnetaz1&lt;/li&gt;
&lt;li&gt;publicsubnetaz2&lt;/li&gt;
&lt;li&gt;natgateway&lt;/li&gt;
&lt;li&gt;routetableprivate&lt;/li&gt;
&lt;li&gt;appprivatesubnetaz1&lt;/li&gt;
&lt;li&gt;appprivatesubnetaz2&lt;/li&gt;
&lt;li&gt;cluster&lt;/li&gt;
&lt;li&gt;clusternodegroup&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fpr5zvfny299lnoiahi55.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fpr5zvfny299lnoiahi55.png" alt="infrasampleappstack.kro.run" width="800" height="273"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Creating an Instance with new CRD InfraSampleAppStack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f sample-app-instance.yaml
infrasampleappstack.kro.run/infrasampleappstack created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Fe1mqzvtremk3eqvosjxe.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fe1mqzvtremk3eqvosjxe.png" alt="kro sample-app-instance" width="800" height="47"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Validating Resources in console.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1e4e0i394k4tsq4rx9zg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1e4e0i394k4tsq4rx9zg.png" alt="Kro Manage a VPC Workflow with the ACK EC2-Controller" width="800" height="222"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2p3ec38ym7de8mf6k2t8.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2p3ec38ym7de8mf6k2t8.png" alt="Kro Manage IAM with the ACK IAM-Controller" width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffte0mjt8lo64mm4wj44o.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffte0mjt8lo64mm4wj44o.png" alt="Kro Manage EKS with the ACK EKS-Controller" width="800" height="244"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When all resources are deployed, the state change from IN_PROGRESS to ACTIVE.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F9dgt3m3b2ot965oxzj9p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F9dgt3m3b2ot965oxzj9p.png" alt="Kro IN_PROGRESS to ACTIVE" width="800" height="70"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deploying an ResourceGraphDefinition for the application
&lt;/h3&gt;

&lt;p&gt;After the all infraestructure is created is time for deploy the application, in this case a popular "Deploy 2048 Game" using a basic pipeline with TEKTON.&lt;/p&gt;

&lt;h3&gt;
  
  
  Installing TEKTON
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt; kubectl create ns tekton-tasks
namespace/tekton-tasks created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Copying secret from aws secret from ack-system to tekton-tasks namespace, this secret is after used for tasks of the pipeline.&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 secret aws-credentials -n ack-system -o yaml \
  | sed "s/namespace: ack-system/namespace: tekton-tasks/" \
  | kubectl apply -f -
secret/aws-credentials created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Installing Tekton CRDS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply --filename https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
namespace/tekton-pipelines created
clusterrole.rbac.authorization.k8s.io/tekton-pipelines-controller-cluster-access created
clusterrole.rbac.authorization.k8s.io/tekton-pipelines-controller-tenant-access created
clusterrole.rbac.authorization.k8s.io/tekton-pipelines-webhook-cluster-access created
clusterrole.rbac.authorization.k8s.io/tekton-events-controller-cluster-access created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Aplying deploy ResourceGraphDefinition
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kcl sample-app-stack.k | kubectl apply -f -
resourcegraphdefinition.kro.run/deploysampleappstack.kro.run created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this case all deploy resources are packaged in a Custom Resource Definition called deploysampleappstack with a KIND &lt;strong&gt;&lt;em&gt;DeploySampleAppStack&lt;/em&gt;&lt;/strong&gt; ready to be instantiated by an end user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fmg0n3dd8iq67es3bplj9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fmg0n3dd8iq67es3bplj9.png" alt="kro deploysampleappstacks " width="800" height="62"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;What resources are created:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;authenticateanddeploy: Is a task that receive 3 parameters, "cluster-name", "aws-region" and "game-yaml-url", this task have 5 steps: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Install kubectl. &lt;/li&gt;
&lt;li&gt;Export the enviroment variable AWS_SHARED_CREDENTIALS_FILE using the secret and after run (aws eks update-kubeconfig --name $(params.cluster-name) --region $(params.aws-region) for connect with the eks cluster.&lt;/li&gt;
&lt;li&gt;Execute an kubectl get nodes for validate connectivity with the cluster&lt;/li&gt;
&lt;li&gt;Deploy the game 2048 with a service that create an classic load balancer using an raw url with the parameter "game-yaml-url".&lt;/li&gt;
&lt;li&gt;exeute an kubectl get svc -n default for retrieve dns from classic load balancer&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;tektonpipeline: refers to the task (authenticateanddeploy) and passes the parameters for the steps.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h3&gt;
  
  
  Creating an Instance with new CRD DeploySampleAppStack
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f sample-app-instance.yaml
deploysampleappstack.kro.run/deploysampleappstack created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Validating Resources
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fndj3j2xbp3spahno9tx1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fndj3j2xbp3spahno9tx1.gif" alt="kro tekton pipeline" width="1472" height="722"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Trigger Tekton Pipeline.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f pipelinerun.yaml
pipelinerun.tekton.dev/deploy-to-eks-run created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When the pipelinerun.yaml is executed a new pod is created where are executed tasks from pipeline that deploying the app in eks cluster.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fbxsqn9a4xwjc0gbh2pvc.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fbxsqn9a4xwjc0gbh2pvc.png" alt="Tekton task" width="800" height="39"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fiy3ksv996i1wiwiqf1cm.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fiy3ksv996i1wiwiqf1cm.png" alt="Tasks logs" width="800" height="209"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fj49i1t6stjg1rdnggq21.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fj49i1t6stjg1rdnggq21.png" alt="dns classic alb" width="800" height="97"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Testing APP.
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8qjnlupp61ra06mqifuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8qjnlupp61ra06mqifuh.png" alt="game 2048" width="800" height="767"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Cleanup.
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl delete -f deploy/pipelinerun.yaml
pipelinerun.tekton.dev "deploy-to-eks-run" deleted
&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;kubectl delete -f deploy/sample-app-instance.yaml
deploysampleappstack.kro.run "deploysampleappstack" deleted
&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;kcl deploy/sample-app-stack.k | kubectl delete -f -
resourcegraphdefinition.kro.run "deploysampleappstack.kro.run" deleted
&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;kubectl delete -f infra/sample-app-instance.yaml
infrasampleappstack.kro.run "infrasampleappstack" deleted
&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;kcl infra/infra-sample-app-stack.k | kubectl delete -f -
resourcegraphdefinition.kro.run "infrasampleappstack.kro.run" deleted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Don't forget clean ALB Classic&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Conclusion: This tutorial takes an approach to deploying applications on AWS EKS using Kro, ACK Controllers, and KCL. This combination of tools significantly reduces code duplication, improves maintainability and overall developer productivity, and provides a robust and efficient workflow for managing Kubernetes deployments on AWS.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>aws</category>
      <category>kro</category>
      <category>kcl</category>
    </item>
    <item>
      <title>Comparing KRO by AWS and Crossplane v1.20</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Wed, 08 Jan 2025 17:32:45 +0000</pubDate>
      <link>https://forem.com/segoja7/comparing-kro-by-aws-and-crossplane-pme</link>
      <guid>https://forem.com/segoja7/comparing-kro-by-aws-and-crossplane-pme</guid>
      <description>&lt;p&gt;Today there is a new opensource tool for kubernetes, is the case of KRO (Kube Resources Orchestator). This a experimental project created by AWS, by the moment in phase beta and not is recommend for productions environment.&lt;/p&gt;

&lt;p&gt;When validating this project I see that it is another tool like Crossplane with a big difference in maturity, both can do the same, but competition is always good, so welcome.&lt;/p&gt;

&lt;h2&gt;
  
  
  Comparating crossplane and KRO
&lt;/h2&gt;

&lt;p&gt;In crossplane for you create an API you need to create a CompositeResourceDefinition and a Composition with this you are enabled your developers for create an claim and deploy applications as API, but in KRO is a little different, the concept is similar but you need an ResourceGroup where are defined all components of the API for that the developers can be create the Application as Instances.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Work KRO.
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://kro.run/docs/getting-started/deploy-a-resource-group" rel="noopener noreferrer"&gt;Check the offical documentacion&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Check my blog related to ACK Controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://dev.to/segoja7/creating-infraestructure-with-the-ack-from-k8s-4dli"&gt;Creating Infraestructure with the ACK from EKS AWS&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Kro is simple and easy,  Kro uses a single ResourceGroup to define and manage collections of Kubernetes resources and automatically creates CRDs and controllers for your custom resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to Work Crossplane.
&lt;/h2&gt;

&lt;p&gt;Check my lasts blogs.&lt;br&gt;
&lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k"&gt;Crossplane + AWS Overview for Managing Infrastructure as Code (IaC) with Kubernetes&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://dev.to/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6"&gt;Crossplane AWS First Demo for Managing Infrastructure as Code (IaC) with Kubernetes.&lt;/a&gt;.&lt;br&gt;
&lt;a href="https://dev.to/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61"&gt;Self-Service: Building and Enabling APIs with Crossplane and AWS&lt;/a&gt;&lt;br&gt;
&lt;a href="https://dev.to/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap"&gt;KCL + Crossplane: A Declarative Language for Deploying Complex Infrastructure on AWS with Kubernetes.&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Compositions and Composite Resource Definitions are key configurations for composing higher-level APIs. The composite resource defines the schema of the new custom API, it is a definition of a new CRD and the Composition is the bridge between the new CRD schema and the existing managed resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;KRO (Kube Resources Orchestator) is a new open-source tool for Kubernetes and this is an experimental project created by AWS and is currently in beta, I think that KRO is similar to Crossplane but less mature.Both help simplify complex applications or architectures for product teams or developers, allowing the complexity to be left to the platform teams.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>crossplane</category>
      <category>kro</category>
      <category>k8s</category>
    </item>
    <item>
      <title>KCL Function+ Crossplane: A Declarative Language for Deploying Complex Infrastructure on AWS with Kubernetes.</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Tue, 19 Nov 2024 15:29:36 +0000</pubDate>
      <link>https://forem.com/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap</link>
      <guid>https://forem.com/segoja7/kcl-crossplane-a-declarative-language-for-deploying-complex-infrastructure-on-aws-with-oap</guid>
      <description>&lt;p&gt;In recent blogs, the exploration of how Crossplane works and its potential to create self-service models by enabling custom APIs has been discussed. The previous example, however, was quite basic.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61" class="crayons-story__hidden-navigation-link"&gt;Self-Service : Building and Enabling APIs with Crossplane and AWS&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/segoja7" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" alt="segoja7 profile" class="crayons-avatar__image" width="512" height="512"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/segoja7" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Javier Sepúlveda
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Javier Sepúlveda
                
              
              &lt;div id="story-author-preview-content-2013634" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/segoja7" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" class="crayons-avatar__image" alt="" width="512" height="512"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Javier Sepúlveda&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Oct 8 '24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61" id="article-link-2013634"&gt;
          Self-Service : Building and Enabling APIs with Crossplane and AWS
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/crossplane"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;crossplane&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/kubernetes"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;kubernetes&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            4 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;This time, the focus shifts to a more advanced concept in Crossplane: functions. &lt;/p&gt;

&lt;p&gt;One limitation of Crossplane is its inability to use loops or conditionals when creating resources. A previous experiment highlighted this challenge, requiring resources to be defined individually. This approach often resulted in manifests that were difficult to manage and prone to complexity, resembling spaghetti code.&lt;/p&gt;

&lt;p&gt;For context, here is an example using only providers: My first steps with Crossplane.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/crossplane_app_aws" rel="noopener noreferrer"&gt;
        crossplane_app_aws
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;To address these issues, functions provide a solution that improves code reusability, adheres to the DRY (Don't Repeat Yourself) principle, and reduces the likelihood of human error. Functions enable the use of complex logic within compositions, making them more robust and easier to maintain.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://marketplace.upbound.io/functions/crossplane-contrib/function-kcl/v0.10.9" rel="noopener noreferrer"&gt;function-kcl&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;By incorporating functions like these, Crossplane compositions can overcome many limitations, becoming more flexible and capable of handling intricate scenarios.&lt;/p&gt;

&lt;h1&gt;
  
  
  Deploying A network Layer with crossplane and KCL.
&lt;/h1&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster (&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Helm version v3.13.1 or later&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.crossplane.io/latest/software/install/" rel="noopener noreferrer"&gt;Crossplane&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;programmatic access AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;This blog assumes that you have all requirements completed and assume that you have installed the providers and the ProviderConfig used in the last blog.&lt;br&gt;
If you have any doubt, please check the this &lt;a href="https://dev.to/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6"&gt;post&lt;/a&gt;.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;Install kcl function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f functions.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.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%2Fiik0zgr4i3ietj1kqj7k.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fiik0zgr4i3ietj1kqj7k.png" alt="crossplane kcl functions" width="474" height="71"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;p&gt;Defined the API using the CompositeResourceDefinition.yaml or XRD.&lt;/p&gt;

&lt;p&gt;In this case, the API only receives: vpccidrBlock, region, and projectName through claim.yaml.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
 name: multiazwordpressinfra.segoja7.example
spec:
 group: segoja7.example
 names:
    kind: MultiAzWordpressInfra
    plural: multiazwordpressinfra
 versions:
   - name: v1alpha1
     served: true
     referenceable: true
     schema:
       openAPIV3Schema:
         type: object
         properties:
           spec:
             type: object
             properties:
               parameters:
                 type: object
                 properties:
                   projectName:
                     type: string
                   vpccidrBlock:
                     type: string
                     default: "172.16.0.0/16"
                   region:
                     type: string
                     default: "us-east-1"
                 required:
                   - region
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step 4.
&lt;/h2&gt;

&lt;p&gt;Composition.&lt;/p&gt;

&lt;p&gt;Crossplane has two modes of composition: pipeline and resouces(Deprecated) check the &lt;a href="https://docs.crossplane.io/latest/concepts/compositions/#create-a-composition" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Following best practices, the compositions have the pipeline mode, and through it, a sequence of steps is defined.&lt;/p&gt;

&lt;p&gt;This is the most important lines for the compositions using kcl function.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  pipeline:
  - step: normal
    functionRef:
      name: function-kcl
    input:
      apiVersion: krm.kcl.dev/v1alpha1
      kind: KCLRun
      metadata:
        name: basic
      spec:
        source: |
# Removed for Brevity
  - step: ready
    functionRef:
      name: function-auto-ready
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;How do KCL functions help users?&lt;/p&gt;

&lt;p&gt;As previously mentioned, when needing to deploy complex infrastructure, Crossplane doesn't directly allow this. Functions become necessary, and with KCL functions, users can solve and improve the code for deploying that infrastructure.&lt;/p&gt;

&lt;p&gt;For example, this is subnets resource with out kcl function. have a declaration for create 4 subnets type private.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;---
apiVersion: ec2.aws.upbound.io/v1beta1
kind: Subnet
metadata:
  name: database-private-subnet-az1
  labels:
    dbsubnet1: private1
spec:
  forProvider:
    availabilityZone: us-east-1a
    cidrBlock: 172.16.1.0/24
    mapPublicIpOnLaunch: false
    region: us-east-1
    tags:
      Name: database-private-subnet-az1
      ManagedBy: crossplane
    vpcIdSelector:
      matchLabels:
        vpc: wordpress
  providerConfigRef:
    name: segoja7
---
apiVersion: ec2.aws.upbound.io/v1beta1
kind: Subnet
metadata:
  name: database-private-subnet-az2
  labels:
    dbsubnet2: private2
spec:
  forProvider:
    availabilityZone: us-east-1b
    cidrBlock: 172.16.2.0/24
    mapPublicIpOnLaunch: false
    region: us-east-1
    tags:
      Name: database-private-subnet-az2
      ManagedBy: crossplane
    vpcIdSelector:
      matchLabels:
        vpc: wordpress
  providerConfigRef:
    name: segoja7
---
apiVersion: ec2.aws.upbound.io/v1beta1
kind: Subnet
metadata:
  name: app-private-subnet-az1
  labels:
    appsubnet1: private1
spec:
  forProvider:
    availabilityZone: us-east-1a
    cidrBlock: 172.16.3.0/24
    mapPublicIpOnLaunch: false
    region: us-east-1
    tags:
      Name: app-private-subnet-az1
      ManagedBy: crossplane
    vpcIdSelector:
      matchLabels:
        vpc: wordpress
  providerConfigRef:
    name: segoja7
---
apiVersion: ec2.aws.upbound.io/v1beta1
kind: Subnet
metadata:
  name: app-private-subnet-az2
  labels:
    appsubnet2: private2
spec:
  forProvider:
    availabilityZone: us-east-1b
    cidrBlock: 172.16.4.0/24
    mapPublicIpOnLaunch: false
    region: us-east-1
    tags:
      Name: app-private-subnet-az2
      ManagedBy: crossplane
    vpcIdSelector:
      matchLabels:
        vpc: wordpress
  providerConfigRef:
    name: segoja7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;And this is an example using kcl-function.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Defining an map of objects for iterate about them.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          database_subnet_configs = [
              {"name": "data-private-subnet-az1", "cidr": "172.16.1.0/24", "zone": "us-east-1a", "type": "private"},
              {"name": "data-private-subnet-az2", "cidr": "172.16.2.0/24", "zone": "us-east-1b", "type": "private"},
              {"name": "app-private-subnet-az1", "cidr": "172.16.3.0/24", "zone": "us-east-1a", "type": "private"},
              {"name": "app-private-subnet-az2", "cidr": "172.16.4.0/24", "zone": "us-east-1b", "type": "private"},
              {"name": "public-subnet-az1", "cidr": "172.16.5.0/24", "zone": "us-east-1a", "type": "public"},
              {"name": "public-subnet-az2", "cidr": "172.16.6.0/24", "zone": "us-east-1b", "type": "public"}
          ]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;ul&gt;
&lt;li&gt;creating subnets using an for.
&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: multiazwordpressinfra-composition
spec:
  compositeTypeRef:
    apiVersion: segoja7.example/v1alpha1
    kind: MultiAzWordpressInfra
  mode: Pipeline
  pipeline:
  - step: normal
    functionRef:
      name: function-kcl
    input:
      apiVersion: krm.kcl.dev/v1alpha1
      kind: KCLRun
      metadata:
        name: basic
      spec:
        source: |
          # Removed for Brevity

          _resources += [
          {
              apiVersion = "ec2.aws.upbound.io/v1beta1"
              kind = "Subnet"
              metadata.name = subnet_config.name
              metadata.labels = {
                    type = subnet_config.type    
              }
              spec.forProvider = {
                  region = region
                  vpcIdSelector.matchControllerRef = True
                  availabilityZone = subnet_config.zone
                  cidrBlock = subnet_config.cidr
                  mapPublicIpOnLaunch = True if subnet_config.type == "public" else False
                  tags = {
                    "app" = "wordpress"
                    "Name" = metadata.name + "-" + projectName
                    "Type" = subnet_config.type
                  }
              }
              spec.providerConfigRef.name = providerConfigName         
          }for subnet_config in database_subnet_configs 
          ]
# Removed for Brevity                                 
          items = _resources
  - step: ready
    functionRef:
      name: function-auto-ready                  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;For this blog the compositions only allow the resources creation of network layer in AWS.&lt;br&gt;
Check all code in this repo.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/crossplane_compositions_kcl" rel="noopener noreferrer"&gt;
        crossplane_compositions_kcl
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is an example using compositions with kcl 
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 5.
&lt;/h2&gt;

&lt;p&gt;The claim is the trigger to deploy the resources defined in the compositions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: segoja7.example/v1alpha1
kind: MultiAzWordpressInfra
metadata:
 name: wordpress-claim
 namespace: default
spec:
  parameters:
    projectName: wordpress-team1s
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this claim, the only parameter for the end user is the project name, which allows the abstraction to be on the platform team side and not the product team side.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 6.
&lt;/h2&gt;

&lt;p&gt;Verify the Resources&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fsgfntdo1he2z1p09dx85.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fsgfntdo1he2z1p09dx85.png" alt="crossplane managed resources" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fneujzqwz8248pv591m1a.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fneujzqwz8248pv591m1a.png" alt="kubectl get managed -A" width="800" height="508"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Please check the following help links, which offer valuable information to improve your understanding of the tool and make the most of its features.&lt;/p&gt;

&lt;p&gt;Usefull links: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/crossplane-contrib/function-kcl" rel="noopener noreferrer"&gt;function-kcl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kcl-lang.io/assets/images/cheatsheet-9dd02ca1109d7a0b8f94114807250496.png" rel="noopener noreferrer"&gt;kcl cheatsheet&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.kcl-lang.io/docs/user_docs/guides/working-with-k8s/mutate-manifests/crossplane-kcl-function" rel="noopener noreferrer"&gt;crossplane-kcl-function&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Conclusion: Crossplane, along with KCL, provides a powerful solution for managing cloud resources more flexibly and efficiently. By enabling the creation of reusable compositions and integrating complex logic, it improves maintainability and reduces errors. Additionally, by abstracting technical details, it eases the work of platform teams, optimizing the experience for end users.&lt;/p&gt;

&lt;p&gt;Thanks to the Crossplane and KCL-Functions community for the support, they helped me with doubts and questions to make this post.&lt;/p&gt;

&lt;p&gt;Thanks for reading this post, let me know if you have any question or comment.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>aws</category>
      <category>crossplane</category>
      <category>iac</category>
    </item>
    <item>
      <title>Self-Service : Building and Enabling APIs with Crossplane and AWS</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Tue, 08 Oct 2024 20:47:52 +0000</pubDate>
      <link>https://forem.com/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61</link>
      <guid>https://forem.com/segoja7/crossplane-aws-self-service-creating-and-enabling-my-own-api-5e61</guid>
      <description>&lt;p&gt;In the first blog of crossplane, a glimpse was taken to a crossplane from an understanding of the key concepts, her definition and make some examples for understanding each component.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" class="crayons-story__hidden-navigation-link"&gt;Crossplane + AWS Overview for Managing Infrastructure as Code (IaC) with Kubernetes&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/segoja7" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" alt="segoja7 profile" class="crayons-avatar__image" width="512" height="512"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/segoja7" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Javier Sepúlveda
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Javier Sepúlveda
                
              
              &lt;div id="story-author-preview-content-1902784" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/segoja7" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" class="crayons-avatar__image" alt="" width="512" height="512"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Javier Sepúlveda&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 26 '24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" id="article-link-1902784"&gt;
          Crossplane + AWS Overview for Managing Infrastructure as Code (IaC) with Kubernetes
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/eks"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;eks&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/crossplane"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;crossplane&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/iac"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;iac&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Can read above.&lt;/p&gt;

&lt;p&gt;In the last blog, work was an exercise of how to deploy a simple app using wordpress with crossplane and creating each layer using Managed resources, that is well, but no is a best practice.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6" class="crayons-story__hidden-navigation-link"&gt;Crossplane AWS First Demo for Managing Infrastructure as Code (IaC) with Kubernetes.&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/segoja7" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" alt="segoja7 profile" class="crayons-avatar__image" width="512" height="512"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/segoja7" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Javier Sepúlveda
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Javier Sepúlveda
                
              
              &lt;div id="story-author-preview-content-1950025" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/segoja7" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" class="crayons-avatar__image" alt="" width="512" height="512"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Javier Sepúlveda&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Aug 30 '24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6" id="article-link-1950025"&gt;
          Crossplane AWS First Demo for Managing Infrastructure as Code (IaC) with Kubernetes.
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/kubernetes"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;kubernetes&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/devops"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;devops&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/cloud"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;cloud&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/crossplane"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;crossplane&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
            &lt;a href="https://dev.to/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            6 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;


&lt;p&gt;Can read above.&lt;/p&gt;

&lt;p&gt;Now is time for applying the best practices using crossplane and make your APIs with a higher level more far from a simple Managed Resources.&lt;/p&gt;

&lt;p&gt;Composition and Composite Resource Definition are the configurations that are used to compose a higher-level API.&lt;/p&gt;

&lt;p&gt;The composite resource defines the schema of the new custom API, it is a definition of a new CRD and the Composition is the bridge between the new CRD schema and the existing managed resources. When the CompositeResourceDefinition and the Composition are done, it is the moment to start provisioning the infrastructure using a resource claim object. &lt;/p&gt;

&lt;p&gt;All this together allow us building reusable infrastructure for our teams, imagine something like to build many APIs or patterns and the teams in a self-service model adding her needs in the car to finally build an app.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F1ggo6jglt5bzu83c5nnd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F1ggo6jglt5bzu83c5nnd.png" alt="crossplane compositions diagram" width="800" height="393"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster (&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Helm version v3.13.1 or later&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.crossplane.io/latest/software/install/" rel="noopener noreferrer"&gt;Crossplane&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;programmatic access AWS&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;This blog assumes that you have all requirements completed and assume that you have installed the providers and the ProviderConfig used in the last blog.&lt;br&gt;
If you have any doubt, please check the last post.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;validating the providers.&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 all -n crossplane-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.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%2F8d7admrurilzwz841b98.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8d7admrurilzwz841b98.png" alt="Validating providers crossplane" width="800" height="564"&gt;&lt;/a&gt;&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 providerconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.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%2Fvrnipyp2s146q700lg5x.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvrnipyp2s146q700lg5x.png" alt="Validating providerconfig crossplane" width="418" height="38"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;With this validation, the environment is ready to provision AWS resources using compositions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;p&gt;It is necessary to know how CompositeResourceDefinition works. Please check this &lt;a href="https://docs.crossplane.io/latest/concepts/composite-resource-definitions/" rel="noopener noreferrer"&gt;link&lt;/a&gt; for more info.&lt;/p&gt;

&lt;p&gt;This is the first CompositeResourceDefinition for defining a higher level API for a VPC in AWS.&lt;/p&gt;

&lt;p&gt;Download the repository for creating the resources.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/crossplane_compositions" rel="noopener noreferrer"&gt;
        crossplane_compositions
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      This is a copy of crossplane_app_aws but using compositions
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;
&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;crossplane_compositions&lt;/h1&gt;

&lt;/div&gt;

&lt;p&gt;This is a copy of crossplane_app_aws but using compositions&lt;/p&gt;

&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;
  &lt;/div&gt;
&lt;br&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/segoja7/crossplane_compositions" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;br&gt;
&lt;/div&gt;
&lt;br&gt;
&lt;br&gt;&lt;br&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: xvpcs.segoja.example # plural.group
spec:
  group: segoja.example #api group
  names:
    kind: Xvpc #singular name
    plural: xvpcs #plural name
  versions:
    - name: v1alpha1 #Define the versions from alpha to pdn or deprecated
      served: true #version actively
      referenceable: true #indicates which version of the schema Compositions use
      schema: # OpenAPI schema
        openAPIV3Schema:
          type: object
          properties:
            spec:
              type: object
              properties:
                parameters:
                  type: object
                  properties:
                    cidrBlock:
                      type: string
                      #default: "10.0.0.0/16"
                    enableDnsHostnames:
                      type: boolean
                      default: true
                    enableDnsSupport:
                      type: boolean
                      default: true
                    region:
                      type: string
                      default: "us-east-1"
                  required:
                    - region
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In this point the compositeResourceDefinition is a new CRD and the Composition like the new controller waiting for a claim for creating the resource according to definitions.&lt;/p&gt;

&lt;p&gt;Note: The section patches is very important because is the unique place that is available for that the user could be personalized the resource, in this case the user could be define the name of the vpc and the cidrblock.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: xvpc-composition
spec:
  compositeTypeRef: #specific version defined in the
    apiVersion: segoja.example/v1alpha1
    kind: Xvpc
  resources: #Array with the list of Managed Resources
    - name: vpc
      base: #Resource template
        apiVersion: ec2.aws.upbound.io/v1beta1
        kind: VPC
        spec:
          forProvider:
            cidrBlock: 172.0.0.0/16
            enableDnsHostnames: true
            enableDnsSupport: true
            region: us-east-1
            tags:
              app: vpc-wordpress
              ManagedBy: crossplane
          providerConfigRef:
            name: segoja7
      patches: #subattributes
        - fromFieldPath: "spec.parameters.cidrBlock"
          toFieldPath: "spec.forProvider.cidrBlock"
        - fromFieldPath: "metadata.name"
          toFieldPath: "spec.forProvider.tags.Name"
        - fromFieldPath: "metadata.name"
          toFieldPath: "metadata.annotations['crossplane.io/external-name']"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The claim allows a user to create the resource that was defined in the compositeResourceDefinition and Additionally, the user could create that resource in the namespace that was assigned for him.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: segoja.example/v1alpha1
kind: Xvpc #singular claim name in the compositeResourceDefinition
metadata:
  name: vpc-wordpress-claim
  namespace: default
spec:
  parameters: #Parameters in the composition
    cidrBlock: 192.178.0.0/16
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4
&lt;/h2&gt;

&lt;p&gt;At that time the first API was build.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -R -f resources/network/vpc/
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The new API xvpcs, to create vpcs.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ff4isd9ab08l1qj8k5p3b.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ff4isd9ab08l1qj8k5p3b.png" alt="Composition api crossplane" width="734" height="66"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fa9xeeldzp28sdtyxgudy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fa9xeeldzp28sdtyxgudy.png" alt="crds crossplane compositions api" width="800" height="291"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The compositeResourceDefinition&lt;br&gt;
&lt;a href="https://media2.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%2Fks1pd6pcqov60pdsjyuj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fks1pd6pcqov60pdsjyuj.png" alt="crossplane composite resource definition" width="800" height="43"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The composition&lt;br&gt;
&lt;a href="https://media2.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%2Ftxa8h1glgvgjq31riv2j.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ftxa8h1glgvgjq31riv2j.png" alt="crossplane compositions" width="800" height="44"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The claim for creating a vpc.&lt;br&gt;
&lt;a href="https://media2.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%2Fu8vh56vaedj2ynfyn8w4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fu8vh56vaedj2ynfyn8w4.png" alt="vpc claim" width="800" height="53"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;This is the vpc in console, as you can see, the vpc have DNS hostnames and DNS resolution enabled by default, the only values that accept the compositions are cidrblock and vpc_name, in this way it is possible to adjust the compositions to the needs of each company or teams.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fvn9robrhweew8ntfud2v.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fvn9robrhweew8ntfud2v.png" alt="vpc console crossplane compositions" width="800" height="226"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusion: This is a practical example of how to quickly enable product teams or developers to use infrastructure or apps quickly, without coding, just using configurations, the platform teams abstracts and encapsulates all the complexity. &lt;/p&gt;

&lt;p&gt;Thanks for reading this post, let me know if you have any question or comment.&lt;/p&gt;

</description>
      <category>crossplane</category>
      <category>aws</category>
      <category>kubernetes</category>
      <category>devops</category>
    </item>
    <item>
      <title>Crossplane AWS First Demo for Managing Infrastructure as Code (IaC) with Kubernetes.</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Fri, 30 Aug 2024 21:21:09 +0000</pubDate>
      <link>https://forem.com/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6</link>
      <guid>https://forem.com/segoja7/crossplane-aws-first-demo-for-managing-infrastructure-as-code-iac-with-kubernetes-part1-55m6</guid>
      <description>&lt;p&gt;In this opportunity is the moment to know with more detail as deployed resources in AWS using resource definitions in crossplane, In the last post we talked about some definitions of crossplane, you can check them in the following link.&lt;/p&gt;


&lt;div class="ltag__link--embedded"&gt;
  &lt;div class="crayons-story "&gt;
  &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" class="crayons-story__hidden-navigation-link"&gt;Crossplane + AWS Overview for Managing Infrastructure as Code (IaC) with Kubernetes&lt;/a&gt;


  &lt;div class="crayons-story__body crayons-story__body-full_post"&gt;
    &lt;div class="crayons-story__top"&gt;
      &lt;div class="crayons-story__meta"&gt;
        &lt;div class="crayons-story__author-pic"&gt;

          &lt;a href="/segoja7" class="crayons-avatar  crayons-avatar--l  "&gt;
            &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" alt="segoja7 profile" class="crayons-avatar__image" width="512" height="512"&gt;
          &lt;/a&gt;
        &lt;/div&gt;
        &lt;div&gt;
          &lt;div&gt;
            &lt;a href="/segoja7" class="crayons-story__secondary fw-medium m:hidden"&gt;
              Javier Sepúlveda
            &lt;/a&gt;
            &lt;div class="profile-preview-card relative mb-4 s:mb-0 fw-medium hidden m:inline-block"&gt;
              
                Javier Sepúlveda
                
              
              &lt;div id="story-author-preview-content-1902784" class="profile-preview-card__content crayons-dropdown branded-7 p-4 pt-0"&gt;
                &lt;div class="gap-4 grid"&gt;
                  &lt;div class="-mt-4"&gt;
                    &lt;a href="/segoja7" class="flex"&gt;
                      &lt;span class="crayons-avatar crayons-avatar--xl mr-2 shrink-0"&gt;
                        &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F1199530%2F9c8a388c-1b7e-4f8d-91cc-ade679dbf051.png" class="crayons-avatar__image" alt="" width="512" height="512"&gt;
                      &lt;/span&gt;
                      &lt;span class="crayons-link crayons-subtitle-2 mt-5"&gt;Javier Sepúlveda&lt;/span&gt;
                    &lt;/a&gt;
                  &lt;/div&gt;
                  &lt;div class="print-hidden"&gt;
                    
                      Follow
                    
                  &lt;/div&gt;
                  &lt;div class="author-preview-metadata-container"&gt;&lt;/div&gt;
                &lt;/div&gt;
              &lt;/div&gt;
            &lt;/div&gt;

          &lt;/div&gt;
          &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" class="crayons-story__tertiary fs-xs"&gt;&lt;time&gt;Jul 26 '24&lt;/time&gt;&lt;span class="time-ago-indicator-initial-placeholder"&gt;&lt;/span&gt;&lt;/a&gt;
        &lt;/div&gt;
      &lt;/div&gt;

    &lt;/div&gt;

    &lt;div class="crayons-story__indention"&gt;
      &lt;h2 class="crayons-story__title crayons-story__title-full_post"&gt;
        &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" id="article-link-1902784"&gt;
          Crossplane + AWS Overview for Managing Infrastructure as Code (IaC) with Kubernetes
        &lt;/a&gt;
      &lt;/h2&gt;
        &lt;div class="crayons-story__tags"&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/aws"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;aws&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/eks"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;eks&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/crossplane"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;crossplane&lt;/a&gt;
            &lt;a class="crayons-tag  crayons-tag--monochrome " href="/t/iac"&gt;&lt;span class="crayons-tag__prefix"&gt;#&lt;/span&gt;iac&lt;/a&gt;
        &lt;/div&gt;
      &lt;div class="crayons-story__bottom"&gt;
        &lt;div class="crayons-story__details"&gt;
          &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left"&gt;
            &lt;div class="multiple_reactions_aggregate"&gt;
              &lt;span class="multiple_reactions_icons_container"&gt;
                  &lt;span class="crayons_icon_container"&gt;
                    &lt;img src="https://assets.dev.to/assets/sparkle-heart-5f9bee3767e18deb1bb725290cb151c25234768a0e9a2bd39370c382d02920cf.svg" width="24" height="24"&gt;
                  &lt;/span&gt;
              &lt;/span&gt;
              &lt;span class="aggregate_reactions_counter"&gt;3&lt;span class="hidden s:inline"&gt; reactions&lt;/span&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/a&gt;
            &lt;a href="https://dev.to/segoja7/crossplane-overview-2f9k#comments" class="crayons-btn crayons-btn--s crayons-btn--ghost crayons-btn--icon-left flex items-center"&gt;
              Comments


              &lt;span class="hidden s:inline"&gt;Add Comment&lt;/span&gt;
            &lt;/a&gt;
        &lt;/div&gt;
        &lt;div class="crayons-story__save"&gt;
          &lt;small class="crayons-story__tertiary fs-xs mr-2"&gt;
            3 min read
          &lt;/small&gt;
            
              &lt;span class="bm-initial"&gt;
                

              &lt;/span&gt;
              &lt;span class="bm-success"&gt;
                

              &lt;/span&gt;
            
        &lt;/div&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/div&gt;
&lt;/div&gt;

&lt;/div&gt;
.
&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Kubernetes cluster (&lt;a href="https://minikube.sigs.k8s.io/docs/start/" rel="noopener noreferrer"&gt;Minikube&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;Helm version v3.13.1 or later&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.crossplane.io/latest/software/install/" rel="noopener noreferrer"&gt;Crossplane&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;programmatic access AWS&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;First, create a profile in minikube&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minikube start -p crossplane
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;With minikube running is moment for install Helm and crossplane, check this &lt;a href="https://docs.crossplane.io/latest/software/install/" rel="noopener noreferrer"&gt;link&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;with the profile of minikube created and helm and crossplane running it is needed to create a txt file, for this case the document name is profile.txt&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;[default]
aws_access_key_id = &amp;lt;Your access key id&amp;gt;
aws_secret_access_key = &amp;lt;Your secret access key&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;when the txt file is created it is necessary created a generic secret.&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 aws-secret -n crossplane-system --from-file=creds=./profile.txt
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Step2.
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Installing a provider
&lt;/h3&gt;

&lt;p&gt;installing provider, in this case providers for rds, ec2, efs and elb.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-ec2
spec:
  package: xpkg.upbound.io/upbound/provider-aws-ec2:v1.12.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-rds
spec:
  package: xpkg.upbound.io/upbound/provider-aws-rds:v1.12.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-efs
spec:
  package: xpkg.upbound.io/upbound/provider-aws-efs:v1.12.0
---
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-elbv2
spec:
  package: xpkg.upbound.io/upbound/provider-aws-elbv2:v1.13.0

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;a href="https://media2.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%2Fzkz8zxvrqkztuhskshi9.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fzkz8zxvrqkztuhskshi9.png" alt="crossplane crds" width="800" height="497"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the provider is installed is time to create an providerconfig, and associated the secret created for autenticated with aws.&lt;/p&gt;
&lt;h2&gt;
  
  
  Configuring the provider
&lt;/h2&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
  name: segoja7
spec:
  credentials:
    source: Secret
    secretRef:
      namespace: crossplane-system
      name: aws-secret
      key: creds
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;In this case, it is using the key from secret with the name creds. &lt;/p&gt;

&lt;p&gt;Note: for this lab it is using a credential, but for other environment type is more recommend used roles.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fniyx316q62fxymkaxtc2.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fniyx316q62fxymkaxtc2.png" alt="crossplane key secret" width="297" height="249"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Architecture
&lt;/h2&gt;

&lt;p&gt;This is a simple wordpress app with high availability.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Ffz59u6skcds7gjwdx4k0.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Ffz59u6skcds7gjwdx4k0.png" alt="crossplane app aws " width="800" height="781"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Step3.
&lt;/h2&gt;

&lt;p&gt;Download the repository for create the resources.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/crossplane_app_aws" rel="noopener noreferrer"&gt;
        crossplane_app_aws
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;



&lt;p&gt;You can check the code in the link above, all the resources are in stack and with the kubectl apply command in a matter of minutes all the services will be deployed in AWS and with the wordpress application ready to install.&lt;/p&gt;

&lt;p&gt;A little of spam&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -R -f resources/
&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;instance.ec2.aws.upbound.io "ec2-wordpress" created
instance.ec2.aws.upbound.io "ec2-wordpress-2" created
elb.elb.aws.upbound.io "wordpress-elb" created
attachment.elb.aws.upbound.io "attachment-elb-wordpress" created
subnetgroup.rds.aws.upbound.io "wordpress-subnetgroup" created
instance.rds.aws.upbound.io "wordpress-dbinstance" created
securitygroup.ec2.aws.upbound.io "ec2securitygroup" created
securitygroupingressrule.ec2.aws.upbound.io "http-rule" created
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-ec2-wordpress-sg" created
securitygroup.ec2.aws.upbound.io "efssecuritygroup" created
securitygroupingressrule.ec2.aws.upbound.io "app-to-efs-rule" created
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-efs-sg" created
securitygroup.ec2.aws.upbound.io "elbsecuritygroup" created
securitygroupingressrule.ec2.aws.upbound.io "world-to-elb-rule" created
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-elb-wordpress-sg" created
securitygroup.ec2.aws.upbound.io "rdssecuritygroup" created
securitygroupingressrule.ec2.aws.upbound.io "app-to-db-rule" created
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-rds-sg" created
vpc.ec2.aws.upbound.io "two-tier-vpc-app" created
subnet.ec2.aws.upbound.io "database-private-subnet-az1" created
subnet.ec2.aws.upbound.io "database-private-subnet-az2" created
subnet.ec2.aws.upbound.io "app-private-subnet-az1" created
subnet.ec2.aws.upbound.io "app-private-subnet-az2" created
subnet.ec2.aws.upbound.io "public-subnet-az1" created
subnet.ec2.aws.upbound.io "public-subnet-az2" created
routetable.ec2.aws.upbound.io "public-route-table" created
routetable.ec2.aws.upbound.io "private-route-table" created
internetgateway.ec2.aws.upbound.io "internetgateway" created
eip.ec2.aws.upbound.io "eip-nat-gateway-az1" created
natgateway.ec2.aws.upbound.io "nat-gateway-az1" created
routetableassociation.ec2.aws.upbound.io "private-route-table-dbassociation1" created
routetableassociation.ec2.aws.upbound.io "private-route-table-dbassociation2" created
routetableassociation.ec2.aws.upbound.io "private-route-table-appassociation1" created
routetableassociation.ec2.aws.upbound.io "private-route-table-appassociation2" created
routetableassociation.ec2.aws.upbound.io "public-route-table1" created
routetableassociation.ec2.aws.upbound.io "public-route-table2" created
route.ec2.aws.upbound.io "publicroute" created
route.ec2.aws.upbound.io "privateroute" created
filesystem.efs.aws.upbound.io "efs-wordpress" created
accesspoint.efs.aws.upbound.io "efs-wordpress" created
filesystempolicy.efs.aws.upbound.io "efs-policy" created
mounttarget.efs.aws.upbound.io "efs-mounttarget-az1" created
mounttarget.efs.aws.upbound.io "efs-mounttarget-az2" created
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With all resouces created is moment of install wordpress, for brevity this step is skiped but you can check the dns name for validating the site and retrieve the rds values for installing wordpress.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fn1h4j9r4gh1y5nmgeccd.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fn1h4j9r4gh1y5nmgeccd.png" alt="wordpress test crossplane" width="800" height="650"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Troubleshooting
&lt;/h2&gt;

&lt;p&gt;In some cases the resources are not created, when the resource is in state ready=false the resource is not deployed and is moment for revise the specs for the desired state of the resource.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F2hj55pte97hiy2cu5stk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F2hj55pte97hiy2cu5stk.png" alt="corssplane elb ready=false" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fc9z4f0fuck7a6z5tj1ik.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fc9z4f0fuck7a6z5tj1ik.png" alt="Describe crossplane elb" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When the spec of the resource is modified, it is moment for apply the resource again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fn4g274o70xbducbe2yz1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fn4g274o70xbducbe2yz1.png" alt="corssplane elb ready=true" width="800" height="449"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Additional is posible make a list of all resources and verify it is status.&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 managed 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2Frogk8b8g8bv085em94nl.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Frogk8b8g8bv085em94nl.png" alt="crossplane managed" width="800" height="581"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Cleanup
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl delete -R -f resources/
instance.ec2.aws.upbound.io "ec2-wordpress" deleted
instance.ec2.aws.upbound.io "ec2-wordpress-2" deleted
elb.elb.aws.upbound.io "wordpress-elb" deleted
attachment.elb.aws.upbound.io "attachment-elb-wordpress" deleted
subnetgroup.rds.aws.upbound.io "wordpress-subnetgroup" deleted
instance.rds.aws.upbound.io "wordpress-dbinstance" deleted
securitygroup.ec2.aws.upbound.io "ec2securitygroup" deleted
securitygroupingressrule.ec2.aws.upbound.io "http-rule" deleted
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-ec2-wordpress-sg" deleted
securitygroup.ec2.aws.upbound.io "efssecuritygroup" deleted
securitygroupingressrule.ec2.aws.upbound.io "app-to-efs-rule" deleted
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-efs-sg" deleted
securitygroup.ec2.aws.upbound.io "elbsecuritygroup" deleted
securitygroupingressrule.ec2.aws.upbound.io "world-to-elb-rule" deleted
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-elb-wordpress-sg" deleted
securitygroup.ec2.aws.upbound.io "rdssecuritygroup" deleted
securitygroupingressrule.ec2.aws.upbound.io "app-to-db-rule" deleted
securitygroupegressrule.ec2.aws.upbound.io "outbound-rule-rds-sg" deleted
vpc.ec2.aws.upbound.io "two-tier-vpc-app" deleted
subnet.ec2.aws.upbound.io "database-private-subnet-az1" deleted
subnet.ec2.aws.upbound.io "database-private-subnet-az2" deleted
subnet.ec2.aws.upbound.io "app-private-subnet-az1" deleted
subnet.ec2.aws.upbound.io "app-private-subnet-az2" deleted
subnet.ec2.aws.upbound.io "public-subnet-az1" deleted
subnet.ec2.aws.upbound.io "public-subnet-az2" deleted
routetable.ec2.aws.upbound.io "public-route-table" deleted
routetable.ec2.aws.upbound.io "private-route-table" deleted
internetgateway.ec2.aws.upbound.io "internetgateway" deleted
eip.ec2.aws.upbound.io "eip-nat-gateway-az1" deleted
natgateway.ec2.aws.upbound.io "nat-gateway-az1" deleted
routetableassociation.ec2.aws.upbound.io "private-route-table-dbassociation1" deleted
routetableassociation.ec2.aws.upbound.io "private-route-table-dbassociation2" deleted
routetableassociation.ec2.aws.upbound.io "private-route-table-appassociation1" deleted
routetableassociation.ec2.aws.upbound.io "private-route-table-appassociation2" deleted
routetableassociation.ec2.aws.upbound.io "public-route-table1" deleted
routetableassociation.ec2.aws.upbound.io "public-route-table2" deleted
route.ec2.aws.upbound.io "publicroute" deleted
route.ec2.aws.upbound.io "privateroute" deleted
filesystem.efs.aws.upbound.io "efs-wordpress" deleted
accesspoint.efs.aws.upbound.io "efs-wordpress" deleted
filesystempolicy.efs.aws.upbound.io "efs-policy" deleted
mounttarget.efs.aws.upbound.io "efs-mounttarget-az1" deleted
mounttarget.efs.aws.upbound.io "efs-mounttarget-az2" deleted
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion:
&lt;/h2&gt;

&lt;p&gt;This is a short overview of how to deploy managed resources using crossplane, in the next post we will make a demo to deploy resources in the console but with compositions.&lt;/p&gt;

&lt;p&gt;Thanks for reading this post, let me know if you have any question or comment.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>devops</category>
      <category>cloud</category>
      <category>crossplane</category>
    </item>
    <item>
      <title>Crossplane + AWS Overview for Managing Infrastructure as Code (IaC) with Kubernetes</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Fri, 26 Jul 2024 15:33:53 +0000</pubDate>
      <link>https://forem.com/segoja7/crossplane-overview-2f9k</link>
      <guid>https://forem.com/segoja7/crossplane-overview-2f9k</guid>
      <description>&lt;p&gt;Crossplane is an open source platform for managing Infrastructure as Code (IaC) using the Kubernetes API. It allows you to define and manage infrastructure resources (such as databases, networks, storage, etc.) declaratively.&lt;/p&gt;

&lt;p&gt;Crossplane is mainly based on Custom Resource Definitions (CRD) or custom controllers that allow us to deploy resources in the cloud provider. Crossplane has other important components such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Providers&lt;/li&gt;
&lt;li&gt;Managed Resources&lt;/li&gt;
&lt;li&gt;Composite Resources&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Providers
&lt;/h2&gt;

&lt;p&gt;Providers are the way to authenticate, make API calls and provide MR drivers with the cloud provider, in this case, AWS. Currently, there are two providers available for use with Crossplane:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/crossplane-contrib/provider-aws" rel="noopener noreferrer"&gt;provider-aws&lt;/a&gt; has less crds, and this provider has more crds &lt;a href="https://github.com/crossplane-contrib/provider-upjet-aws" rel="noopener noreferrer"&gt;provider-upjet-aws&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;The RDS Provider installs a second Provider, the upbound-provider-family-aws.&lt;br&gt;
The family provider manages authentication to AWS across all AWS family Providers.&lt;/p&gt;

&lt;p&gt;It is also necessary to create a ControllerConfig, mainly used for credentials (in the case of EKS, a service account):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: pkg.crossplane.io/v1beta1
kind: DeploymentRuntimeConfig
metadata:
  name: runtime-config
spec:
  serviceAccountTemplate:
    metadata:
      annotations:
    eks.amazonaws.com/role-arn: arn:aws:iam::123456789111:role/crossplane-role-controller
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is an example Provider for deploy RDS&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: provider-aws-rds
spec:
  package: xpkg.upbound.io/upbound/provider-aws-rds:v1.9.1
  runtimeConfigRef:
    name: runtime-config
&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;apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
  name: provider-config
spec:
  credentials:
    source: IRSA
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Create a DeploymentRuntimeConfig to associate the IAM role ARN.&lt;/li&gt;
&lt;li&gt;Apply the DeploymentRuntimeConfig to the Provider.&lt;/li&gt;
&lt;li&gt;Instruct the ProviderConfig to use IRSA credentials.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;When your provider is installed, you can see the new CRDS&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fgp4ggb6etq2bj648xvuq.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fgp4ggb6etq2bj648xvuq.png" alt="AWS RDS CRDS" width="791" height="428"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Managed Resources (MR).
&lt;/h2&gt;

&lt;p&gt;A managed resource (MR) connects a CRD to a controller that deploys the resource. For example, an RDS instance in AWS is an MR, represented in a YAML file that defines an RDS instance.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: rds.aws.upbound.io/v1beta2
kind: Instance
metadata:
  annotations:
    meta.upbound.io/example-id: rds/v1beta1/instance
    uptest.upbound.io/timeout: "3600"
  labels:
    testing.upbound.io/example-name: example-dbinstance
  name: example-dbinstance
spec:
  forProvider:
    allocatedStorage: 20
    autoGeneratePassword: true
    autoMinorVersionUpgrade: true
    backupRetentionPeriod: 14
    backupWindow: 09:46-10:16
    dbName: example
    engine: postgres
    engineVersion: "16.1"
    instanceClass: db.t3.micro
    maintenanceWindow: Mon:00:00-Mon:03:00
    passwordSecretRef:
      key: password
      name: example-dbinstance
      namespace: crossplane-system
    publiclyAccessible: false
    region: us-east-1
    skipFinalSnapshot: true
    storageEncrypted: true
    storageType: gp2
    username: adminuser
  providerConfigRef:
    name: providerconfig
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Crossplane has the ability to revert any changes to the resource that are not contemplated in the YAML file, using this file as the only source of truth.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this point you can create a resource, in this case an RDS instance with default values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Composite resources (XR)
&lt;/h2&gt;

&lt;p&gt;Composite resources allow complex resources to be created and managed. This abstracts the complexity of creating multiple resources and encapsulates the logic and configuration of various infrastructure resources.&lt;/p&gt;

&lt;p&gt;There are two types: composite resources (XR) and composite resource claims (XRC), which facilitate infrastructure management in a declarative and reusable manner.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;XRs are used in the CompositeResourceDefinition type and their main purpose is to combine related managed resources into a single stack and build reusable infrastructure template APIs.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;The following are the critical components in an XR:&lt;br&gt;
Composite Resource Definition (XRD)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
  name: compositerdsinstances.database.example.org
spec:
  group: database.example.org
  names:
    kind: CompositeRDSInstance
    plural: compositerdsinstances
  claimNames:
    kind: RDSInstance
    plural: rdsinstances
  versions:
  - name: v1
    served: true
    referenceable: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              parameters:
                type: object
                properties:
                  storageGB:
                    type: integer
                  version:
                    type: string
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Composition&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
  name: compositerdsinstances.aws.database.example.org
spec:
  compositeTypeRef:
    apiVersion: database.example.org/v1alpha1
    kind: CompositeRDSInstance
  resources:
  - base:
      apiVersion: rds.aws.crossplane.io/v1beta1
      kind: DBInstance
      spec:
        forProvider:
          dbInstanceClass: db.t3.micro
          allocatedStorage: 20
          engine: postgres
          engineVersion: "13"
          masterUsername: admin
    patches:
    - fromFieldPath: "spec.parameters.storageGB"
      toFieldPath: "spec.forProvider.allocatedStorage"
    - fromFieldPath: "spec.parameters.version"
      toFieldPath: "spec.forProvider.engineVersion"

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;• Claim (XRCs)&lt;/p&gt;

&lt;p&gt;XRCs allow users to request XR instances easily and consistently.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: database.example.org/v1alpha1
kind: RDSInstance
metadata:
  name: my-rds-claim
spec:
  parameters:
    storageGB: 20
    version: "13"
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conclusion: This is a short overview of important resources used in crossplane to start a deployment of new resources of a manner declarative, in the next post we make a demo deploy resources in the console.&lt;/p&gt;

&lt;p&gt;Thanks for reading this post, let me know if you have any question or comment.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>eks</category>
      <category>crossplane</category>
      <category>iac</category>
    </item>
    <item>
      <title>Creating Infraestructure with the ACK from EKS AWS.</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Thu, 27 Jun 2024 21:14:51 +0000</pubDate>
      <link>https://forem.com/segoja7/creating-infraestructure-with-the-ack-from-k8s-4dli</link>
      <guid>https://forem.com/segoja7/creating-infraestructure-with-the-ack-from-k8s-4dli</guid>
      <description>&lt;p&gt;Cloud people!&lt;/p&gt;

&lt;p&gt;The turn in this occasion is for the AWS controller for k8s (ack).&lt;/p&gt;

&lt;p&gt;I believe that traditional Infrastructure as Code (IaC) tools have some limitations. The transition towards solutions such as Crossplane or similar projects is inevitable and, possibly, in a short time this evolution will be adopted. At another time, we could discuss in detail the pros and cons of these tools.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/cli/latest/userguide/install-cliv2.html" rel="noopener noreferrer"&gt;AWS CLI&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/tools/" rel="noopener noreferrer"&gt;Kubectl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.terraform.io/downloads.html" rel="noopener noreferrer"&gt;Terraform&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://k9scli.io/topics/install/" rel="noopener noreferrer"&gt;k9s&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;K8s cluster (You can use a local cluster or in this demo an eks cluster.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Let's see how we can do this.&lt;/p&gt;

&lt;h2&gt;
  
  
  Reference Architecture
&lt;/h2&gt;

&lt;p&gt;In this demo Terraform is used to deploy infrastructure base where ack will be executed.&lt;/p&gt;

&lt;p&gt;Please check this &lt;a href="https://aws-controllers-k8s.github.io/community/docs/community/how-it-works/" rel="noopener noreferrer"&gt;link&lt;/a&gt; for architecture reference.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1.
&lt;/h2&gt;

&lt;p&gt;In this step you need to deploy a cluster of k8s and all that necessary for that cluster work. For a better brevity, the code is shared in this repository.&lt;br&gt;
&lt;/p&gt;
&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/segoja7" rel="noopener noreferrer"&gt;
        segoja7
      &lt;/a&gt; / &lt;a href="https://github.com/segoja7/ack_controller_demo" rel="noopener noreferrer"&gt;
        ack_controller_demo
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
&lt;/div&gt;
 
&lt;h2&gt;
  
  
  Step 2.
&lt;/h2&gt;

&lt;p&gt;With the eks cluster in this case running you need to install the controller inside the cluster, in this opportunity is used helm with the provider of terraform. Check the code. Aditional you need to create a service account with least privileges permissions, in this case our   controller is for ec2, with a policy of ec2 is enough and the name of namespace.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "ack-role-for-service-accounts-eks" {

  source  = "terraform-aws-modules/iam/aws//modules/iam-role-for-service-accounts-eks"
  version = "5.39.1"

  role_name        = local.workspace["role_name"]
  role_policy_arns = local.workspace["role_policy_arns"]

  oidc_providers = local.workspace["oidc_providers"]

  tags = merge(
    var.required_tags,
    local.workspace["tags"]
  )
}

&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;      role_policy_arns = {
        policy = "arn:aws:iam::aws:policy/AmazonEC2FullAccess"
      }

      oidc_providers = {
        ex = {
          provider_arn               = var.oidc_provider_arn
          namespace_service_accounts = ["ack-system:ack-ec2-controller"]
        }
      }

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 3.
&lt;/h2&gt;

&lt;p&gt;With the service account created, It is time to deploy the controller, in this case an ec2 controller.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;module "eks-blueprints-addons" {
  source  = "aws-ia/eks-blueprints-addons/aws"
  version = "1.16.2"

  cluster_name      = local.workspace["cluster_name"]
  cluster_endpoint  = local.workspace["cluster_endpoint"]
  cluster_version   = local.workspace["cluster_version"]
  oidc_provider_arn = local.workspace["oidc_provider_arn"]
  helm_releases     = local.workspace["helm_releases"]
}
&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_releases = {
        ec2-controller= {
          name                = "ec2-controller"
          description         = "A Helm chart for ack ec2-controller"
          repository_username = data.aws_ecrpublic_authorization_token.token.user_name
          repository_password = data.aws_ecrpublic_authorization_token.token.password
          namespace           = "ack-system"
          chart_version       = "1.2.12"
          chart               = "ec2-chart"
          create_namespace    = true
          repository          = "oci://public.ecr.aws/aws-controllers-k8s"
          values = [templatefile("./helm-charts/ack_ec2_controller/values.yaml", {
            role-arn = var.role_arn_controller
            region   = "us-east-1"
          })]
        }
      }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 4.
&lt;/h2&gt;

&lt;p&gt;Validating controller.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fjdkpszkidd1jl8a0jaqp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fjdkpszkidd1jl8a0jaqp.png" alt="ack ec2 controller" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;remember that this controller have permissions all this resources, not only ec2 instances. :D&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://media2.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%2Fawucuqn2z8b4qzt1hrtj.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2Fawucuqn2z8b4qzt1hrtj.png" alt="ack ec2 controller crd" width="701" height="398"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 5.
&lt;/h2&gt;

&lt;p&gt;With the controller running without problems, now it is possible to create resources. For that there is the following raw manifest.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;apiVersion: ec2.services.k8s.aws/v1alpha1
kind: Instance
metadata:
  name: segoja7-ack
spec:
  imageID: ami-023c11a32b0207432
  instanceType: t3.micro
  subnetID: subnet-0365ed0ebddcdb2a0
  tags:
    - key: ManagedBy
      value: ec2-controller
    - key: Name
      value: segoja7-ack
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.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%2F0p00co1vs3cysd1gpjcc.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F0p00co1vs3cysd1gpjcc.gif" alt="ack ec2 controller deployment" width="751" height="513"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.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%2F8s0s0wn5xiiatvizb25s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.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%2F8s0s0wn5xiiatvizb25s.png" alt="ec2 console" width="800" height="217"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Conclusion: In this demo, It is demonstrated how to deploy an ack controller, in this case for ec2 service, create a role with permissions for the service account and deploy the resource from eks. &lt;/p&gt;

&lt;p&gt;Thanks for reading this post, let me know if you have any question or comment.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ack</category>
      <category>k8s</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Test</title>
      <dc:creator>Javier Sepúlveda</dc:creator>
      <pubDate>Tue, 25 Jun 2024 20:34:05 +0000</pubDate>
      <link>https://forem.com/segoja7/cross-plane-the-next-phase-of-infrastructure-automation-testing-infrastructure-with-crossplane-in-aws-3j3n</link>
      <guid>https://forem.com/segoja7/cross-plane-the-next-phase-of-infrastructure-automation-testing-infrastructure-with-crossplane-in-aws-3j3n</guid>
      <description>&lt;p&gt;Test&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
