Crossplane: Gestión de Infraestructura en Kubernetes
Crossplane convierte Kubernetes en un plano de control universal para gestionar infraestructura en la nube utilizando los mismos mecanismos declarativos que usas para tus aplicaciones. Esta guía explica cómo instalar Crossplane, configurar proveedores, crear recursos gestionados, composiciones y habilitar flujos GitOps para el aprovisionamiento de infraestructura.
Requisitos Previos
- Clúster Kubernetes 1.26+ (kind, k3s, EKS, GKE, AKS o similar)
kubectlconfigurado apuntando al clúster- Helm 3.x instalado
- Credenciales de proveedor cloud (AWS, GCP, Azure, etc.)
# Verificar la versión de Kubernetes
kubectl version --short
# Verificar Helm
helm version --short
Instalación de Crossplane
# Añadir el repositorio Helm de Crossplane
helm repo add crossplane-stable https://charts.crossplane.io/stable
helm repo update
# Instalar Crossplane en el namespace dedicado
helm install crossplane \
crossplane-stable/crossplane \
--namespace crossplane-system \
--create-namespace \
--version 1.14.0
# Verificar que los pods están corriendo
kubectl get pods -n crossplane-system
Salida esperada:
NAME READY STATUS RESTARTS AGE
crossplane-7d9f4c6b9-xk8mz 1/1 Running 0 2m
crossplane-rbac-manager-5b8f9c7d6-vt2pq 1/1 Running 0 2m
# Instalar la CLI de Crossplane (kubectl crossplane)
curl -sL https://raw.githubusercontent.com/crossplane/crossplane/master/install.sh | sh
mv crossplane /usr/local/bin/
# Verificar la instalación
kubectl crossplane --version
Instalación de Proveedores
Los proveedores son el puente entre Crossplane y los servicios cloud:
# Instalar el proveedor de 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:v0.47.0
EOF
# Verificar que el proveedor se instaló correctamente
kubectl get providers
kubectl describe provider provider-aws-s3
Configurar las credenciales del proveedor:
# Crear el Secret con las credenciales de AWS
cat << 'EOF' > /tmp/aws-credentials.txt
[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
EOF
kubectl create secret generic aws-secret \
-n crossplane-system \
--from-file=creds=/tmp/aws-credentials.txt
# Crear el ProviderConfig para AWS
cat << 'EOF' | kubectl apply -f -
apiVersion: aws.upbound.io/v1beta1
kind: ProviderConfig
metadata:
name: default
spec:
credentials:
source: Secret
secretRef:
namespace: crossplane-system
name: aws-secret
key: creds
EOF
# Limpiar el archivo temporal con credenciales
rm /tmp/aws-credentials.txt
Recursos Gestionados
Un Managed Resource (MR) es la representación de un recurso cloud en Kubernetes:
# Crear un bucket S3 con Crossplane
cat << 'EOF' | kubectl apply -f -
apiVersion: s3.aws.upbound.io/v1beta1
kind: Bucket
metadata:
name: mi-bucket-crossplane
annotations:
crossplane.io/external-name: mi-bucket-produccion-2024
spec:
forProvider:
region: eu-west-1
tags:
Entorno: produccion
Gestionado: crossplane
providerConfigRef:
name: default
EOF
# Monitorear el estado del recurso
kubectl get bucket mi-bucket-crossplane
kubectl describe bucket mi-bucket-crossplane
# Crear una base de datos RDS
cat << 'EOF' | kubectl apply -f -
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
metadata:
name: mi-base-datos
spec:
forProvider:
region: eu-west-1
instanceClass: db.t3.micro
engine: postgres
engineVersion: "15.4"
dbName: miapp
username: admin
passwordSecretRef:
namespace: default
name: rds-password
key: password
allocatedStorage: 20
skipFinalSnapshot: true
providerConfigRef:
name: default
EOF
Composiciones y XRDs
Las Composiciones permiten abstraer recursos complejos en APIs personalizadas:
# Definir un XRD (Composite Resource Definition)
cat << 'EOF' | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: CompositeResourceDefinition
metadata:
name: xpostgresqlinstances.plataforma.empresa.com
spec:
group: plataforma.empresa.com
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:
parameters:
type: object
properties:
storageGB:
type: integer
description: "Tamaño del almacenamiento en GB"
version:
type: string
description: "Versión de PostgreSQL"
required:
- storageGB
EOF
# Crear la Composition que implementa el XRD
cat << 'EOF' | kubectl apply -f -
apiVersion: apiextensions.crossplane.io/v1
kind: Composition
metadata:
name: postgresql-aws
labels:
provider: aws
servicio: postgresql
spec:
compositeTypeRef:
apiVersion: plataforma.empresa.com/v1alpha1
kind: XPostgreSQLInstance
resources:
- name: rds-instance
base:
apiVersion: rds.aws.upbound.io/v1beta1
kind: Instance
spec:
forProvider:
region: eu-west-1
engine: postgres
instanceClass: db.t3.micro
username: admin
skipFinalSnapshot: true
patches:
# Parchar el tamaño del disco desde los parámetros del claim
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.storageGB
toFieldPath: spec.forProvider.allocatedStorage
# Parchar la versión del motor
- type: FromCompositeFieldPath
fromFieldPath: spec.parameters.version
toFieldPath: spec.forProvider.engineVersion
EOF
Claims de Infraestructura
Los Claims son la interfaz que usan los equipos de desarrollo para solicitar infraestructura:
# Los desarrolladores crean Claims en su propio namespace
cat << 'EOF' | kubectl apply -f -
apiVersion: plataforma.empresa.com/v1alpha1
kind: PostgreSQLInstance
metadata:
name: bd-mi-aplicacion
namespace: equipo-backend
spec:
parameters:
storageGB: 20
version: "15.4"
compositionSelector:
matchLabels:
provider: aws
writeConnectionSecretToRef:
name: credenciales-postgres
EOF
# Verificar el estado del claim
kubectl get postgresqlinstance -n equipo-backend
# Ver los recursos compuestos creados
kubectl get composite
# Ver las credenciales de conexión generadas
kubectl get secret credenciales-postgres -n equipo-backend -o yaml
Flujos GitOps con Crossplane
Integrar Crossplane con Argo CD o Flux para GitOps:
# Estructura de repositorio GitOps recomendada
mkdir -p infra/{compositions,claims,providerconfigs}
# El repositorio se organiza así:
# infra/
# ├── compositions/ # Definiciones de XRDs y Compositions
# ├── claims/ # Claims por entorno y equipo
# └── providerconfigs/ # Configuraciones de proveedores (sin credenciales)
# Ejemplo de Application de Argo CD para Crossplane
cat << 'EOF' | kubectl apply -f -
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: infraestructura-crossplane
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/mi-org/infra-gitops
targetRevision: main
path: infra/compositions
destination:
server: https://kubernetes.default.svc
namespace: crossplane-system
syncPolicy:
automated:
prune: true
selfHeal: true
EOF
Solución de Problemas
# Verificar el estado de los proveedores
kubectl get providers
kubectl describe provider provider-aws-s3
# Ver los eventos de un recurso gestionado
kubectl describe bucket mi-bucket-crossplane | grep -A 20 Events
# Ver los logs del pod del proveedor
kubectl logs -n crossplane-system \
$(kubectl get pods -n crossplane-system -l pkg.crossplane.io/revision -o name | head -1)
# Verificar recursos compuestos y su estado
kubectl get composite
kubectl get managed
# Depurar un claim que no se resuelve
kubectl describe postgresqlinstance bd-mi-aplicacion -n equipo-backend
# Forzar la sincronización de un recurso
kubectl annotate bucket mi-bucket-crossplane \
crossplane.io/paused="true" --overwrite
kubectl annotate bucket mi-bucket-crossplane \
crossplane.io/paused="false" --overwrite
El provider no se conecta:
# Verificar que el Secret de credenciales existe
kubectl get secret aws-secret -n crossplane-system
# Verificar la configuración del ProviderConfig
kubectl describe providerconfig default
Conclusión
Crossplane representa una evolución natural del Infrastructure as Code, permitiendo gestionar recursos cloud usando la misma API declarativa de Kubernetes que ya conoces. Las Composiciones son el elemento más poderoso ya que permiten crear abstracciones que ocultan la complejidad a los equipos de desarrollo, mientras que GitOps garantiza que el estado deseado siempre se aplica de forma auditable. Con Crossplane, la infraestructura se convierte en un ciudadano de primera clase en tu ecosistema Kubernetes.


