DevOps & CI/CD

Crossplane: Infraestrutura como Código dentro do Kubernetes na Prática

13 min de leitura

Crossplane: Infraestrutura como Código dentro do Kubernetes na Prática

O que é Crossplane e por que você deve aprender Crossplane é um framework open-source que traz o conceito de Infrastructure as Code (IaC) para dentro do Kubernetes, permitindo que você provisione e gerencie recursos em nuvens (AWS, Azure, GCP) usando manifestos YAML nativos do Kubernetes. Em vez de usar ferramentas separadas como Terraform ou CloudFormation, você define sua infraestrutura através de Custom Resources (CRs) que o Kubernetes orquestra. A grande vantagem é unificar o gerenciamento: aplicações, configurações e infraestrutura vivem no mesmo cluster, com o mesmo padrão declarativo. Você ganha versionamento de infraestrutura, RBAC nativo, GitOps pronto para usar, e elimina a necessidade de pipelines separados para aplicação e infraestrutura. Isso é especialmente poderoso em ambientes cloud-native onde a flexibilidade e a automação são críticas. Arquitetura e Conceitos Fundamentais Componentes Principais A arquitetura do Crossplane repousa em três pilares: o control plane (o próprio cluster Kubernetes), providers (conectores para serviços em nuvem) e managed resources (representações dos recursos reais

<h2>O que é Crossplane e por que você deve aprender</h2>

<p>Crossplane é um framework open-source que traz o conceito de Infrastructure as Code (IaC) para dentro do Kubernetes, permitindo que você provisione e gerencie recursos em nuvens (AWS, Azure, GCP) usando manifestos YAML nativos do Kubernetes. Em vez de usar ferramentas separadas como Terraform ou CloudFormation, você define sua infraestrutura através de Custom Resources (CRs) que o Kubernetes orquestra.</p>

<p>A grande vantagem é unificar o gerenciamento: aplicações, configurações e infraestrutura vivem no mesmo cluster, com o mesmo padrão declarativo. Você ganha versionamento de infraestrutura, RBAC nativo, GitOps pronto para usar, e elimina a necessidade de pipelines separados para aplicação e infraestrutura. Isso é especialmente poderoso em ambientes cloud-native onde a flexibilidade e a automação são críticas.</p>

<h2>Arquitetura e Conceitos Fundamentais</h2>

<h3>Componentes Principais</h3>

<p>A arquitetura do Crossplane repousa em três pilares: o <strong>control plane</strong> (o próprio cluster Kubernetes), <strong>providers</strong> (conectores para serviços em nuvem) e <strong>managed resources</strong> (representações dos recursos reais na nuvem).</p>

<p>Quando você instala o Crossplane no cluster, ele implanta controllers que ficam observando os CRs. Se você cria um recurso do tipo <code>RDSInstance</code>, o controller do provider AWS detecta e provisiona uma instância RDS real na sua conta. O estado é sincronizado: mudanças no manifest atualizam a nuvem, e mudanças na nuvem (detectadas via polling) são refletidas no Kubernetes.</p>

<h3>Providers e Composições</h3>

<p><strong>Providers</strong> são pacotes que estendem o Kubernetes com novos tipos de recursos. O provider AWS adiciona RDSInstance, S3Bucket, VPC, etc. Você pode instalar múltiplos providers no mesmo cluster, permitindo gerenciar infraestrutura multi-cloud.</p>

<p><strong>Composições</strong> (Compositions) são o ponto forte: permitem criar abstrações sobre recursos brutos. Por exemplo, em vez de expor toda a complexidade de criar um banco RDS (security groups, parameter groups, backups), você cria um CompositeResourceDefinition (XRD) chamado <code>PostgreSQL</code> que encapsula tudo. Aplicações usam apenas <code>PostgreSQL</code>, isoladas da complexidade.</p>

<h2>Instalação e Configuração Inicial</h2>

<h3>Instalando Crossplane</h3>

<p>A instalação é simples via Helm. Certifique-se de ter um cluster Kubernetes rodando (versão 1.16+) e acesso à conta de nuvem desejada.</p>

<pre><code class="language-bash"># Adicionar repositório Helm

helm repo add crossplane-stable https://charts.crossplane.io/stable

helm repo update

Instalar Crossplane no namespace crossplane-system

helm install crossplane crossplane-stable/crossplane \

--namespace crossplane-system \

--create-namespace \

--wait</code></pre>

<p>Verifique se está rodando:</p>

<pre><code class="language-bash">kubectl get pods -n crossplane-system

Você deve ver crossplane e crossplane-rbac-manager rodando</code></pre>

<h3>Instalando um Provider</h3>

<p>Vamos usar o provider AWS. Crie um manifesto YAML com a definição do provider:</p>

<pre><code class="language-yaml">apiVersion: pkg.crossplane.io/v1

kind: Provider

metadata:

name: upbound-provider-aws

spec:

package: xpkg.upbound.io/upbound-provider-aws:v0.45.0</code></pre>

<p>Aplique no cluster:</p>

<pre><code class="language-bash">kubectl apply -f provider.yaml

kubectl get providers</code></pre>

<p>O Crossplane baixa o pacote e instala os CRDs automaticamente. Aguarde alguns minutos até que o status mude para <code>Healthy</code>.</p>

<h3>Configurando Credenciais</h3>

<p>Para que o provider acesse sua conta AWS, você precisa configurar credenciais. Crie um arquivo <code>credentials.txt</code> com sua chave de acesso:</p>

<pre><code>[default]

aws_access_key_id = YOUR_ACCESS_KEY

aws_secret_access_key = YOUR_SECRET_KEY</code></pre>

<p>Crie um Secret no Kubernetes:</p>

<pre><code class="language-bash">kubectl create secret generic aws-secret \

-n crossplane-system \

--from-file=creds=./credentials.txt</code></pre>

<p>Agora, crie uma <code>ProviderConfig</code> que informa ao provider como usar essas credenciais:</p>

<pre><code class="language-yaml">apiVersion: aws.crossplane.io/v1beta1

kind: ProviderConfig

metadata:

name: default

spec:

credentials:

source: Secret

secretRef:

namespace: crossplane-system

name: aws-secret

key: creds

region: us-east-1</code></pre>

<p>Aplique:</p>

<pre><code class="language-bash">kubectl apply -f provider-config.yaml</code></pre>

<p>A partir de agora, qualquer recurso AWS que você criar usará essa ProviderConfig automaticamente.</p>

<h2>Provisionando Recursos Gerenciados</h2>

<h3>Seu Primeiro Recurso: Um Bucket S3</h3>

<p>Vamos criar um bucket S3 simples usando Crossplane. Crie um manifesto:</p>

<pre><code class="language-yaml">apiVersion: s3.aws.crossplane.io/v1

kind: Bucket

metadata:

name: meu-bucket-crossplane

spec:

forProvider:

region: us-east-1

acl: private

providerConfigRef:

name: default</code></pre>

<p>Aplique:</p>

<pre><code class="language-bash">kubectl apply -f s3-bucket.yaml</code></pre>

<p>Verifique o status:</p>

<pre><code class="language-bash">kubectl get buckets

kubectl describe bucket meu-bucket-crossplane</code></pre>

<p>Em segundos, você verá o bucket criado na sua conta AWS. Se deletar o manifesto, o bucket é deletado automaticamente (por padrão). Isso é IaC real: sua infraestrutura vive como código no Git.</p>

<h3>Criando um Banco de Dados RDS PostgreSQL</h3>

<p>Um exemplo mais realista: provisionar um RDS PostgreSQL. Este manifesto cria a instância, a subnet group e handles automaticamente:</p>

<pre><code class="language-yaml">apiVersion: rds.aws.crossplane.io/v1

kind: DBInstance

metadata:

name: meu-postgres

spec:

forProvider:

dbInstanceIdentifier: meu-postgres

engine: postgres

engineVersion: &quot;15.3&quot;

dbInstanceClass: db.t3.micro

masterUsername: admin

masterUserPassword: &quot;SuperSenha123!&quot; # Melhor usar Secret

allocatedStorage: &quot;20&quot;

region: us-east-1

skipFinalSnapshot: true

publiclyAccessible: false

providerConfigRef:

name: default</code></pre>

<pre><code class="language-bash">kubectl apply -f rds.yaml</code></pre>

<p>Aguarde alguns minutos. O Crossplane provisiona a instância e sincroniza o status no manifesto. Você pode inspecionar:</p>

<pre><code class="language-bash">kubectl get dbinstances

kubectl describe dbinstance meu-postgres</code></pre>

<h3>Melhor Prática: Usar Secrets para Senhas</h3>

<p>Nunca hardcode senhas. Use Kubernetes Secrets e referencie via <code>connectionSecretRef</code>:</p>

<pre><code class="language-yaml">apiVersion: rds.aws.crossplane.io/v1

kind: DBInstance

metadata:

name: meu-postgres-seguro

spec:

forProvider:

dbInstanceIdentifier: meu-postgres-seguro

engine: postgres

engineVersion: &quot;15.3&quot;

dbInstanceClass: db.t3.micro

masterUsername: admin

allocatedStorage: &quot;20&quot;

region: us-east-1

skipFinalSnapshot: true

connectionSecretRef:

namespace: default

name: postgres-creds

providerConfigRef:

name: default</code></pre>

<p>O Crossplane cria automaticamente um Secret <code>postgres-creds</code> contendo endpoint, porta e credenciais. Suas aplicações podem montar esse Secret.</p>

<h2>Abstraindo Complexidade com Composições</h2>

<h3>O Problema de Expor Complexidade</h3>

<p>Expor todos os detalhes de RDS (security groups, parameter groups, backups, replication) para cada desenvolvedor criar é caótico. Eles precisam conhecer detalhes AWS, não de negócio. A solução: Composições.</p>

<h3>Criando um CompositeResourceDefinition (XRD)</h3>

<p>Um XRD define um novo tipo de recurso abstrato. Crie <code>postgresql-xrd.yaml</code>:</p>

<pre><code class="language-yaml">apiVersion: apiextensions.crossplane.io/v1

kind: CompositeResourceDefinition

metadata:

name: xpostgresqls.my.company

spec:

group: my.company

names:

kind: XPostgreSQL

plural: xpostgresqls

claimNames:

kind: PostgreSQL

plural: postgresqls

versions:

  • name: v1alpha1

served: true

referenceable: true

schema:

openAPIV3Schema:

type: object

properties:

spec:

type: object

properties:

size:

type: string

enum: [&quot;small&quot;, &quot;medium&quot;, &quot;large&quot;]

default: &quot;small&quot;

storageGB:

type: integer

default: 20

required:

  • size
  • storageGB

status:

type: object

properties:

endpoint:

type: string

port:

type: integer</code></pre>

<p>Aplique:</p>

<pre><code class="language-bash">kubectl apply -f postgresql-xrd.yaml</code></pre>

<p>Agora você tem dois novos tipos: <code>XPostgreSQL</code> (recurso composto interno) e <code>PostgreSQL</code> (reclamação para aplicações).</p>

<h3>Criando a Composition</h3>

<p>A Composition mapeia os parâmetros abstratos para recursos AWS reais. Crie <code>postgresql-composition.yaml</code>:</p>

<pre><code class="language-yaml">apiVersion: apiextensions.crossplane.io/v1

kind: Composition

metadata:

name: postgresql-aws

spec:

compositeTypeRef:

apiVersion: my.company/v1alpha1

kind: XPostgreSQL

resources:

  • name: rds-instance

base:

apiVersion: rds.aws.crossplane.io/v1

kind: DBInstance

spec:

forProvider:

engine: postgres

engineVersion: &quot;15.3&quot;

region: us-east-1

skipFinalSnapshot: true

connectionSecretRef:

namespace: default

providerConfigRef:

name: default

patches:

  • fromFieldPath: &quot;spec.size&quot;

toFieldPath: &quot;spec.forProvider.dbInstanceClass&quot;

transforms:

  • type: map

map:

small: &quot;db.t3.micro&quot;

medium: &quot;db.t3.small&quot;

large: &quot;db.t3.medium&quot;

  • fromFieldPath: &quot;spec.storageGB&quot;

toFieldPath: &quot;spec.forProvider.allocatedStorage&quot;

  • fromFieldPath: &quot;metadata.uid&quot;

toFieldPath: &quot;spec.forProvider.dbInstanceIdentifier&quot;

transforms:

  • type: string

string:

fmt: &quot;pg-%s&quot;

  • fromFieldPath: &quot;metadata.name&quot;

toFieldPath: &quot;spec.connectionSecretRef.name&quot;</code></pre>

<p>Aplique:</p>

<pre><code class="language-bash">kubectl apply -f postgresql-composition.yaml</code></pre>

<h3>Usando a Composição</h3>

<p>Agora, desenvolvedores usam apenas:</p>

<pre><code class="language-yaml">apiVersion: my.company/v1alpha1

kind: PostgreSQL

metadata:

name: app-database

namespace: production

spec:

size: medium

storageGB: 50</code></pre>

<pre><code class="language-bash">kubectl apply -f app-database.yaml</code></pre>

<p>O Crossplane automaticamente provisiona um RDS <code>db.t3.small</code> com 50GB de armazenamento. Simples, limpo, seguro. A Composition encapsula boas práticas: backups, tagging, networking.</p>

<h2>Padrões Avançados e Boas Práticas</h2>

<h3>GitOps com Crossplane</h3>

<p>A maior força do Crossplane é integração nativa com GitOps. Use Flux ou ArgoCD:</p>

<pre><code class="language-yaml">apiVersion: source.toolkit.fluxcd.io/v1beta2

kind: GitRepository

metadata:

name: infra-repo

namespace: flux-system

spec:

interval: 1m

url: https://github.com/seu-usuario/infrastructure-repo

ref:

branch: main

---

apiVersion: kustomize.toolkit.fluxcd.io/v1

kind: Kustomization

metadata:

name: infra-kustomize

namespace: flux-system

spec:

interval: 10m

sourceRef:

kind: GitRepository

name: infra-repo

path: ./crossplane-resources

prune: true

wait: true</code></pre>

<p>Toda mudança no Git provoca alteração de infraestrutura automaticamente. Auditoria completa, rollback fácil, histórico versionado.</p>

<h3>Usando XRD com Policies e Validação</h3>

<p>Você pode adicionar policies ao XRD para forçar padrões corporativos:</p>

<pre><code class="language-yaml">apiVersion: my.company/v1alpha1

kind: PostgreSQL

metadata:

name: app-database

spec:

size: large # Vai gerar erro se não estiver na enum

storageGB: 5 # Pode adicionar validação de mínimo</code></pre>

<p>Use <code>validation.rules</code> no OpenAPI schema do XRD para validações complexas.</p>

<h3>Monitoramento e Troubleshooting</h3>

<p>Inspecione o status detalhado:</p>

<pre><code class="language-bash">kubectl describe postgresql app-database

Mostra condições, eventos, recursos criados</code></pre>

<p>Verifique logs do controller:</p>

<pre><code class="language-bash">kubectl logs -n crossplane-system deployment/crossplane -f</code></pre>

<p>Use <code>kubectl get events -n default</code> para ver eventos de reconciliação.</p>

<h2>Conclusão</h2>

<p>Aprendemos que <strong>Crossplane unifica aplicações e infraestrutura sob o mesmo paradigma Kubernetes</strong>, eliminando silos e ferramentas paralelas. Você provisionou recursos AWS em YAML puro, com reconciliação automática e sincronização de estado.</p>

<p>Segundo, <strong>Composições são o mecanismo de abstração que habilita plataformas internas</strong>: desenvolvedores trabalham com conceitos de negócio (<code>PostgreSQL</code>, <code>WebApp</code>) enquanto a Composition garante boas práticas, compliance e padrões corporativos. Isso escala em organizações grandes.</p>

<p>Terceiro, <strong>GitOps com Crossplane fornece auditoria, versionamento e rollback de infraestrutura</strong> que outras ferramentas não oferecem nativamente. Sua infraestrutura é código, tratado como tal.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://docs.crossplane.io/" target="_blank" rel="noopener noreferrer">Documentação Oficial Crossplane</a></li>

<li><a href="https://docs.crossplane.io/latest/concepts/compositions/" target="_blank" rel="noopener noreferrer">Crossplane Composition Guide</a></li>

<li><a href="https://marketplace.upbound.io/providers/upbound/provider-aws/" target="_blank" rel="noopener noreferrer">Upbound Provider AWS</a></li>

<li><a href="https://www.cncf.io/" target="_blank" rel="noopener noreferrer">Infrastructure as Code with Kubernetes - Brennan Saeta (Cloud Native Computing Foundation)</a></li>

<li><a href="https://fluxcd.io/flux/concepts/" target="_blank" rel="noopener noreferrer">GitOps with Flux and Crossplane - Flux Documentation</a></li>

</ul>

<p>&lt;!-- FIM --&gt;</p>

Comentários

Mais em DevOps & CI/CD

Como Usar Gerenciamento de Processos no Linux: systemd, journald e Serviços em Produção
Como Usar Gerenciamento de Processos no Linux: systemd, journald e Serviços em Produção

Entendendo o systemd: O Coração do Linux Moderno O systemd é o sistema de ini...

Feature Flags: como realizar deploys mais seguros e confiáveis
Feature Flags: como realizar deploys mais seguros e confiáveis

A gestão de mudanças no código-fonte de um sistema é uma tarefa constante e d...

Kubernetes Fundamentos: Arquitetura, Componentes e kubectl na Prática: Do Básico ao Avançado
Kubernetes Fundamentos: Arquitetura, Componentes e kubectl na Prática: Do Básico ao Avançado

Entendendo Kubernetes: O Orquestrador de Contêineres Kubernetes é uma platafo...