Crossplane: Transformando o Kubernetes em um Painel de Controle Multi‑Cloud
Arquitetura base do Crossplane
crossplane estende o plano de controle do kubernetes com CRDs que representam recursos de provedores de nuvem. Cada provedor (AWS, GCP, azure, etc.) expõe um ProviderConfig que encapsula credenciais e região. O controlador do provedor traduz as especificações declarativas em chamadas API nativas, mantendo o estado desejado como ManagedResources. Essa camada permite que o cluster funcione como um orquestrador de infraestrutura, eliminando a necessidade de ferramentas externas para provisionamento.
Instalação via Helm
O caminho mais rápido para colocar o Crossplane em produção é usar o chart oficial. O comando abaixo cria o namespace crossplane-system e instala a versão estável:
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm upgrade --install crossplane crossplane-stable/crossplane
--namespace crossplane-system
--create-namespace
--set args={--debug}
Após a instalação, verifique os pods:
kubectl get pods -n crossplane-system
Configuração de provedores de nuvem
Para cada nuvem, crie um ProviderConfig que aponta para um secret contendo as credenciais. Exemplo para AWS:
apiVersion: v1
kind: Secret
metadata:
name: aws-creds
namespace: crossplane-system
type: Opaque
stringData:
key: "[YOUR_AWS_ACCESS_KEY_ID]"
secret: "[YOUR_AWS_SECRET_ACCESS_KEY]"
---
apiVersion: aws.crossplane.io/v1beta1
kind: ProviderConfig
metadata:
name: aws-provider
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: key
secretKey: secret
region: us-east-1
O mesmo padrão se aplica a GCP (gcp.crossplane.io/v1beta1) e Azure (azure.crossplane.io/v1beta1), mudando apenas o tipo de secret e os campos de configuração.
Validação automática
Crossplane executa um webhook de validação que impede a criação de recursos com credenciais ausentes ou regiões incompatíveis. O log do controlador exibe mensagens como ProviderConfig not found quando o secret está mal referenciado, facilitando o CI/CD.
Composições (Compositions) e Claims
O poder do Crossplane reside nas Compositions, que agrupam múltiplos ManagedResources em um único recurso de alto nível (Claim). Um exemplo clássico: provisionar um banco de dados PostgreSQL com VPC, sub‑rede e regras de firewall em apenas um XPostgreSQLInstance.
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
metadata:
name: prod-db
spec:
parameters:
storageGB: 100
engineVersion: "13"
writeConnectionSecretToRef:
name: prod-db-conn
namespace: default
A composição que atende esse claim fica em um Composition separado:
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstance-aws
spec:
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: vpc
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: VPC
spec:
forProvider:
cidrBlock: 10.0.0.0/16
patches:
- fromFieldPath: "metadata.labels[environment]"
toFieldPath: "spec.forProvider.tags[environment]"
- name: subnet
base:
apiVersion: ec2.aws.crossplane.io/v1beta1
kind: Subnet
spec:
forProvider:
cidrBlock: 10.0.1.0/24
vpcId: "${resource.vpc.id}"
patches:
- fromFieldPath: "metadata.labels[environment]"
toFieldPath: "spec.forProvider.tags[environment]"
- name: rds
base:
apiVersion: rds.aws.crossplane.io/v1beta1
kind: DBInstance
spec:
forProvider:
dbInstanceClass: db.t3.medium
engine: postgres
allocatedStorage: 100
masterUsername: admin
masterPasswordSecretRef:
name: prod-db-conn
namespace: default
key: password
patches:
- fromFieldPath: "spec.parameters.storageGB"
toFieldPath: "spec.forProvider.allocatedStorage"
- fromFieldPath: "spec.parameters.engineVersion"
toFieldPath: "spec.forProvider.engineVersion"
Observe o uso de ${resource.vpc.id} para referenciar dinamicamente o ID da VPC criada anteriormente. Essa interpolação elimina scripts ad‑hoc e garante consistência transacional.
Automação via GitOps
Armazene o manifesto da Claim e da Composition em um repositório Git. O ArgoCD ou Flux monitora o diretório infrastructure/ e aplica as mudanças automaticamente. Exemplo de kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- provider-aws.yaml
- composition-postgres.yaml
- claim-prod-db.yaml
Com o webhook do repositório configurado, qualquer PR que altere storageGB dispara um rollout que atualiza o recurso RDS sem intervenção manual.
Gerenciamento de segredos e rotatividade
Crossplane cria um Secret contendo as credenciais de conexão (host, porta, usuário, senha). Para rotatividade automática, combine o controlador crossplane/provider-aws com o external-secrets da comunidade. O fluxo:
- O provedor de segredos (AWS Secrets Manager) armazena a senha.
- O
ExternalSecretsincroniza o valor para o secretprod-db-conn. - Crossplane detecta a mudança e reinicia o
DBInstancecom a nova senha.
Manifesto de ExternalSecret:
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: prod-db-conn
spec:
secretStoreRef:
name: aws-secret-store
kind: SecretStore
target:
name: prod-db-conn
creationPolicy: Owner
dataFrom:
- extract:
key: /prod/postgres/password
Políticas de controle de acesso (RBAC) avançado
Crossplane respeita o RBAC nativo do Kubernetes. Defina ClusterRole e ClusterRoleBinding que concedem permissão apenas para recursos específicos, por exemplo, permitir que a equipe de dados crie apenas XPostgreSQLInstance e nada mais.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: data-team-crossplane
rules:
- apiGroups: ["database.example.org"]
resources: ["xpostgresqlinstances"]
verbs: ["create","get","list","watch","delete"]
- apiGroups: ["apiextensions.crossplane.io"]
resources: ["compositions"]
verbs: ["get","list","watch"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: data-team-binding
subjects:
- kind: Group
name: data-team
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: data-team-crossplane
apiGroup: rbac.authorization.k8s.io
Essa segmentação impede que usuários criem recursos fora do escopo, reduzindo a superfície de ataque.
Observabilidade e métricas
Crossplane expõe métricas via Prometheus no endpoint /metrics. Ative o ServiceMonitor se usar o Prometheus Operator:
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
name: crossplane-monitor
labels:
release: prometheus
spec:
selector:
matchLabels:
app.kubernetes.io/name: crossplane
endpoints:
- port: metrics
interval: 30s
As métricas crossplane_resource_claims_total e crossplane_managed_resource_status permitem criar alertas que detectam falhas de provisionamento antes que impactem a aplicação.
Integração com OpenTelemetry
Instale o collector sidecar no namespace crossplane-system e configure o exportador para o backend de sua escolha (Jaeger, Tempo). O collector captura spans gerados pelos controladores ao chamar APIs de nuvem, oferecendo rastreamento de latência de provisionamento.
apiVersion: opentelemetry.io/v1alpha1
kind: OpenTelemetryCollector
metadata:
name: crossplane-collector
spec:
mode: deployment
config: |
receivers:
otlp:
protocols:
grpc:
exporters:
otlp:
endpoint: tempo:4317
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp]
Escalabilidade e alta disponibilidade
Crossplane pode ser executado em modo HA usando múltiplas réplicas do controlador. Defina o Deployment com replicas: 3 e habilite o leader election via flag --leader-election. O Helm chart já inclui essa configuração, basta sobrescrever:
helm upgrade --install crossplane crossplane-stable/crossplane
--namespace crossplane-system
--set replicaCount=3
--set args={--leader-election}
O etcd do cluster Kubernetes garante consistência de estado; o controlador persiste o status em status.conditions de cada recurso, permitindo que réplicas concorrentes reconciliem sem conflitos.
Destruição controlada e políticas de retenção
Ao deletar um Claim, o Crossplane executa a política DeletionPolicy definida na Composition. Opções:
Delete: remove o recurso gerenciado imediatamente.Orphan: deixa o recurso na nuvem, útil para migrações.Retain: mantém o recurso, mas remove a referência do Kubernetes.
Exemplo de Claim com política de retenção:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
metadata:
name: staging-db
spec:
deletionPolicy: Orphan
parameters:
storageGB: 50
engineVersion: "13"
Essa granularidade evita perdas acidentais em ambientes de teste, enquanto ainda permite a limpeza automática em produção.
Pipeline CI/CD completa
Um pipeline típico usa GitHub Actions para validar o YAML, aplicar via kubectl e monitorar o status com kubectl wait. Exemplo de workflow:
name: Deploy Infra
on:
push:
paths:
- 'infrastructure/**'
jobs:
apply:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up kubectl
uses: azure/setup-kubectl@v3
with:
version: 'v1.28.0'
- name: Apply manifests
run: |
kubectl apply -k infrastructure/
- name: Wait for DB
run: |
kubectl wait --for=condition=Ready XPostgreSQLInstance/prod-db --timeout=10m
O comando kubectl wait bloqueia o job até que o recurso atinja o estado Ready, garantindo que a aplicação downstream só seja implantada após a infraestrutura estar pronta.
Sou um profissional na área de Tecnologia da informação, especializado em monitoramento de ambientes, Sysadmin e na cultura DevOps. Possuo certificações de Segurança, AWS e Zabbix.


