Crossplane: gerenciando infraestrutura cloud como recursos Kubernetes
1. Introdução ao Crossplane e a Filosofia de Infraestrutura como Código no Kubernetes
Crossplane é um projeto open-source mantido pela Cloud Native Computing Foundation (CNCF) que transforma o Kubernetes em um plano de controle universal para gerenciar infraestrutura cloud. Diferente de ferramentas tradicionais como Terraform ou Pulumi, que operam fora do ecossistema Kubernetes, o Crossplane permite que equipes definam e provisionem recursos de cloud (bancos de dados, buckets, redes) usando a mesma API declarativa do Kubernetes.
A principal vantagem está na unificação: times de plataforma e aplicação compartilham o mesmo cluster Kubernetes como ponto central de gerenciamento. Isso elimina a necessidade de ferramentas externas, pipelines separados e contextos diferentes para infraestrutura e aplicações.
2. Arquitetura e Componentes Principais do Crossplane
Crossplane é construído sobre três conceitos fundamentais:
Providers: São extensões que conectam o Crossplane a provedores cloud (AWS, GCP, Azure, Oracle) ou serviços específicos (Datadog, GitHub). Cada provider expõe Managed Resources que representam recursos reais da nuvem.
Managed Resources: São objetos Kubernetes que mapeiam diretamente para recursos cloud. Por exemplo, um Bucket do provider AWS S3 ou um DBInstance do provider AWS RDS.
Composite Resources (XRs) e Claims: XRs permitem agrupar múltiplos Managed Resources em um único objeto personalizado. Claims são versões simplificadas que times de aplicação criam para consumir infraestrutura sem conhecer detalhes internos.
3. Instalação e Configuração Inicial do Crossplane no Cluster
A instalação pode ser feita via Helm:
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
helm install crossplane crossplane-stable/crossplane --namespace crossplane-system --create-namespace
Após instalar, configure um Provider. Exemplo com AWS:
cat <<EOF | kubectl apply -f -
apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
name: provider-aws-s3
spec:
package: xpkg.upbound.io/upbound/provider-aws-s3:v1.10.0
EOF
Para autenticação, crie um Secret com as credenciais AWS:
apiVersion: v1
kind: Secret
metadata:
name: aws-creds
namespace: crossplane-system
stringData:
credentials: |
[default]
aws_access_key_id = AKIA...
aws_secret_access_key = ...
E um ProviderConfig referenciando o Secret:
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds
key: credentials
Agora, crie seu primeiro Managed Resource — um bucket S3:
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
name: meu-bucket-crossplane
spec:
forProvider:
region: us-east-1
providerConfigRef:
name: default
4. Criando Composite Resources (XRs) para Abstração de Infraestrutura
Composite Resources permitem criar templates reutilizáveis. Primeiro, defina um CompositeResourceDefinition (XRD) — o schema do recurso composto:
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.database.example.org
spec:
group: database.example.org
names:
kind: XPostgreSQLInstance
plural: xpostgresqlinstances
claimNames:
kind: PostgreSQLInstance
plural: postgresqlinstances
versions:
- name: v1alpha1
served: true
referenceable: true
schema:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
storageGB:
type: integer
default: 20
engineVersion:
type: string
default: "15"
Depois, crie uma Composition que mapeia esse XRD para recursos reais:
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: xpostgresqlinstances.aws.database.example.org
spec:
compositeTypeRef:
apiVersion: database.example.org/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: subnetgroup
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: SubnetGroup
spec:
forProvider:
region: us-east-1
subnetIds:
- subnet-123
- subnet-456
- name: securitygroup
base:
apiVersion: ec2.aws.upbound.io/v1beta1
kind: SecurityGroup
spec:
forProvider:
region: us-east-1
ingress:
- fromPort: 5432
toPort: 5432
protocol: tcp
cidrBlocks:
- "10.0.0.0/8"
- name: database
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
region: us-east-1
dbInstanceClass: db.t3.micro
engine: postgres
allocatedStorage: 20
engineVersion: "15"
masterUsername: admin
masterPasswordSecretRef:
name: db-password
namespace: crossplane-system
patches:
- type: FromCompositeFieldPath
fromFieldPath: spec.storageGB
toFieldPath: spec.forProvider.allocatedStorage
- type: FromCompositeFieldPath
fromFieldPath: spec.engineVersion
toFieldPath: spec.forProvider.engineVersion
5. Consumindo Infraestrutura com Claims
Times de aplicação criam apenas um Claim simples:
apiVersion: database.example.org/v1alpha1
kind: PostgreSQLInstance
metadata:
name: meu-postgres-app
namespace: aplicacao
spec:
storageGB: 50
engineVersion: "16"
writeConnectionSecretToRef:
name: db-connection
O Crossplane automaticamente provisiona o subnet group, security group e instância RDS, expondo os detalhes de conexão no Secret db-connection.
6. Gerenciamento de Ciclo de Vida
Crossplane gerencia dependências automaticamente. Se você definir um recurso que depende de outro (ex: RDS depende de subnet), ele aguarda a criação do recurso pai.
Atualizações em Compositions não afetam recursos já criados — apenas novos Claims usam a versão mais recente. Para migrar recursos existentes, é necessário atualizar manualmente os Managed Resources ou recriar os Claims.
O drift detection é nativo: Crossplane reconcilia continuamente o estado desejado com o real na cloud, corrigindo alterações manuais.
7. Integração com GitOps
Armazene XRD, Composition e Providers em um repositório Git:
infra/
├── crossplane/
│ ├── providers/
│ │ └── provider-aws.yaml
│ ├── xrds/
│ │ └── postgres-instance.yaml
│ └── compositions/
│ └── postgres-instance.yaml
Com ArgoCD ou Flux, sincronize esses arquivos com o cluster. Para controle de acesso, use RBAC do Kubernetes:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: aplicacao
name: claim-creator
rules:
- apiGroups: ["database.example.org"]
resources: ["postgresqlinstances"]
verbs: ["create", "get", "list", "watch", "delete"]
8. Casos de Uso Avançados e Considerações de Segurança
Para múltiplas contas AWS, crie diferentes ProviderConfigs:
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: conta-producao
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-creds-producao
Para segurança, integre com HashiCorp Vault usando o provider vault e armazene senhas como secrets gerenciados. Aplique o princípio de menor privilégio: cada ProviderConfig deve ter permissões específicas apenas para os recursos que gerencia.
Monitore com métricas do Crossplane (disponíveis via Prometheus) e configure health checks para detectar recursos em estado degradado.
Referências
- Documentação Oficial do Crossplane — Guia completo de instalação, conceitos e referência de API
- Crossplane no GitHub — Código fonte, issues e discussões da comunidade
- Tutorial: Composite Resources no Crossplane — Artigo aprofundado sobre criação de XRs e Compositions
- Crossplane com GitOps e ArgoCD — Guia oficial do ArgoCD para integração com Crossplane
- Provedores Oficiais do Crossplane (Upbound) — Catálogo de providers para AWS, GCP, Azure e outros serviços
- Crossplane e Segurança: Gerenciamento de Segredos — Práticas recomendadas para autenticação e autorização