<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: "15.3"
dbInstanceClass: db.t3.micro
masterUsername: admin
masterUserPassword: "SuperSenha123!" # Melhor usar Secret
allocatedStorage: "20"
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: "15.3"
dbInstanceClass: db.t3.micro
masterUsername: admin
allocatedStorage: "20"
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: ["small", "medium", "large"]
default: "small"
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: "15.3"
region: us-east-1
skipFinalSnapshot: true
connectionSecretRef:
namespace: default
providerConfigRef:
name: default
patches:
- fromFieldPath: "spec.size"
toFieldPath: "spec.forProvider.dbInstanceClass"
transforms:
- type: map
map:
small: "db.t3.micro"
medium: "db.t3.small"
large: "db.t3.medium"
- fromFieldPath: "spec.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
- fromFieldPath: "metadata.uid"
toFieldPath: "spec.forProvider.dbInstanceIdentifier"
transforms:
- type: string
string:
fmt: "pg-%s"
- fromFieldPath: "metadata.name"
toFieldPath: "spec.connectionSecretRef.name"</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><!-- FIM --></p>