DevOps Admin

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

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

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 na nuvem).

Quando você instala o Crossplane no cluster, ele implanta controllers que ficam observando os CRs. Se você cria um recurso do tipo RDSInstance, 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.

Providers e Composições

Providers 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.

Composições (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 PostgreSQL que encapsula tudo. Aplicações usam apenas PostgreSQL, isoladas da complexidade.

Instalação e Configuração Inicial

Instalando Crossplane

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

# 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

Verifique se está rodando:

kubectl get pods -n crossplane-system
# Você deve ver crossplane e crossplane-rbac-manager rodando

Instalando um Provider

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

apiVersion: pkg.crossplane.io/v1
kind: Provider
metadata:
  name: upbound-provider-aws
spec:
  package: xpkg.upbound.io/upbound-provider-aws:v0.45.0

Aplique no cluster:

kubectl apply -f provider.yaml
kubectl get providers

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

Configurando Credenciais

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

[default]
aws_access_key_id = YOUR_ACCESS_KEY
aws_secret_access_key = YOUR_SECRET_KEY

Crie um Secret no Kubernetes:

kubectl create secret generic aws-secret \
  -n crossplane-system \
  --from-file=creds=./credentials.txt

Agora, crie uma ProviderConfig que informa ao provider como usar essas credenciais:

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

Aplique:

kubectl apply -f provider-config.yaml

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

Provisionando Recursos Gerenciados

Seu Primeiro Recurso: Um Bucket S3

Vamos criar um bucket S3 simples usando Crossplane. Crie um manifesto:

apiVersion: s3.aws.crossplane.io/v1
kind: Bucket
metadata:
  name: meu-bucket-crossplane
spec:
  forProvider:
    region: us-east-1
    acl: private
  providerConfigRef:
    name: default

Aplique:

kubectl apply -f s3-bucket.yaml

Verifique o status:

kubectl get buckets
kubectl describe bucket meu-bucket-crossplane

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.

Criando um Banco de Dados RDS PostgreSQL

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

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
kubectl apply -f rds.yaml

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

kubectl get dbinstances
kubectl describe dbinstance meu-postgres

Melhor Prática: Usar Secrets para Senhas

Nunca hardcode senhas. Use Kubernetes Secrets e referencie via connectionSecretRef:

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

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

Abstraindo Complexidade com Composições

O Problema de Expor Complexidade

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.

Criando um CompositeResourceDefinition (XRD)

Um XRD define um novo tipo de recurso abstrato. Crie postgresql-xrd.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

Aplique:

kubectl apply -f postgresql-xrd.yaml

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

Criando a Composition

A Composition mapeia os parâmetros abstratos para recursos AWS reais. Crie postgresql-composition.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"

Aplique:

kubectl apply -f postgresql-composition.yaml

Usando a Composição

Agora, desenvolvedores usam apenas:

apiVersion: my.company/v1alpha1
kind: PostgreSQL
metadata:
  name: app-database
  namespace: production
spec:
  size: medium
  storageGB: 50
kubectl apply -f app-database.yaml

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

Padrões Avançados e Boas Práticas

GitOps com Crossplane

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

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

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

Usando XRD com Policies e Validação

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

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

Use validation.rules no OpenAPI schema do XRD para validações complexas.

Monitoramento e Troubleshooting

Inspecione o status detalhado:

kubectl describe postgresql app-database
# Mostra condições, eventos, recursos criados

Verifique logs do controller:

kubectl logs -n crossplane-system deployment/crossplane -f

Use kubectl get events -n default para ver eventos de reconciliação.

Conclusão

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

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

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

Referências


Artigos relacionados