Architettura dei Componenti CAPI

Cluster API implementa un’architettura modulare basata sul pattern dei controller Kubernetes, dove ogni componente ha responsabilità specifiche e ben definite. Questa separazione delle responsabilità garantisce estensibilità, manutenibilità e testabilità del sistema.

Management Cluster vs Workload Cluster

La distinzione fondamentale in CAPI è la separazione tra il cluster che gestisce l’infrastruttura e i cluster che eseguono i workload applicativi.

Management Cluster

Il Management Cluster serve come hub di controllo centrale per l’infrastruttura Kubernetes. Le sue caratteristiche principali includono:

Responsabilità operative:

  • Hosting dei controller CAPI core
  • Archiviazione delle Custom Resource Definitions che rappresentano lo stato desiderato
  • Orchestrazione del ciclo di vita dei Workload Cluster
  • Gestione delle credenziali di accesso all’infrastruttura

Requisiti tecnici:

  • Cluster Kubernetes standard (può essere locale con kind)
  • Accesso di rete ai provider di infrastruttura
  • Capacità computazionale limitata (principalmente per i controller)
  • High availability opzionale ma raccomandata per ambienti production

Workload Cluster

I Workload Cluster rappresentano i cluster Kubernetes di destinazione dove vengono deployate le applicazioni business. Caratteristiche distintive:

Lifecycle gestito dichiarativamente:

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: workload-cluster-01
spec:
  controlPlaneRef:
    kind: TalosControlPlane
    name: workload-cluster-01-control-plane
  infrastructureRef:
    kind: ProxmoxCluster 
    name: workload-cluster-01-proxmox

Noi definiamo solamente le caratteristiche che desideriamo, in questo caso un control plane gestito tramite il controller TalosControlPlane, e il sistema si occupa di come raggiungere questo stato.

Isolamento operativo:

  • Nessun accesso diretto ai componenti CAPI
  • Gestione tramite kubeconfig generato automaticamente
  • Scaling e maintenance orchestrati dal Management Cluster

Componenti Core di CAPI

CAPI Core Components

CAPI Core Controller

Il Core Controller rappresenta il cervello operativo di CAPI, responsabile dell’orchestrazione di alto livello del ciclo di vita dei cluster.

Cluster Controller

Il Cluster Controller gestisce la risorsa Cluster, coordinando l’interazione tra infrastructure provider e control plane provider:

Funzioni principali:

  • Validazione della configurazione del cluster
  • Orchestrazione della sequenza di provisioning
  • Gestione dello stato controlPlaneReady e infrastructureReady
  • Generazione del kubeconfig per l’accesso al workload cluster

Reconciliation logic:

// Pseudocodice del reconciliation loop
func (r *ClusterReconciler) Reconcile(ctx context.Context, req ctrl.Request) {
    // 1. Fetch cluster object
    cluster := &clusterv1.Cluster{}
    
    // 2. Reconcile infrastructure
    if !cluster.Status.InfrastructureReady {
        return r.reconcileInfrastructure(ctx, cluster)
    }
    
    // 3. Reconcile control plane  
    if !cluster.Status.ControlPlaneReady {
        return r.reconcileControlPlane(ctx, cluster)
    }
    
    // 4. Generate kubeconfig
    return r.reconcileKubeconfig(ctx, cluster)
}

Machine Controller

Il Machine Controller gestisce il ciclo di vita delle singole istanze di calcolo che compongono il cluster:

Responsabilità operative:

  • Coordinamento con Infrastructure Provider per provisioning VM
  • Gestione del processo di bootstrap tramite Bootstrap Provider
  • Monitoring dello stato dei nodi e recovery automatico
  • Implementazione delle politiche di sostituzione per oggetti Machine immutabili

Stati del ciclo di vita:

status:
  phase: "Running"  # Pending, Provisioning, Provisioned, Running, Deleting, Failed
  addresses:
    - type: "InternalIP"
      address: "192.168.1.100"
  nodeRef:
    kind: "Node"
    name: "workload-cluster-01-control-plane-abc123"

Bootstrap Provider

Il “bootstrap provider” in Kubernetes Cluster API è un componente fondamentale che si occupa di inizializzare il primo nodo di un nuovo cluster Kubernetes, noto come “control plane node” o “master node”. In parole semplici, è il motore che avvia il cluster. Esistono diverse implementazioni in base al “modo” in cui vogliamo che il cluster sia inizializzato

Kubeadm Bootstrap Provider

Il provider kubeadm rappresenta l’implementazione di riferimento, utilizzando kubeadm per l’inizializzazione dei nodi:

Generazione cloud-init:

apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
kind: KubeadmConfig
metadata:
  name: worker-node-config
spec:
  joinConfiguration:
    nodeRegistration:
      kubeletExtraArgs:
        cloud-provider: external
  preKubeadmCommands:
    - "swapoff -a"
    - "modprobe br_netfilter"
  postKubeadmCommands:
    - "kubectl label node ${HOSTNAME} node-role.kubernetes.io/worker="

Talos Bootstrap Provider

Il Talos Bootstrap Provider genera configurazioni specifiche per Talos Linux:

Configurazione Talos:

apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3
kind: TalosConfig  
metadata:
  name: talos-worker-config
spec:
  generateType: "join"
  talosVersion: "v1.7.0"
  configPatches:
    - op: "add"
      path: "/machine/network/interfaces"
      value:
        - interface: "eth0"
          dhcp: true

Control Plane Provider

Il “control plane provider” in Kubernetes Cluster API è un componente chiave che si occupa della gestione del piano di controllo del cluster (control plane) dopo che il primo nodo è stato inizializzato. A differenza del bootstrap provider, che si limita ad avviare il primo nodo, il control plane provider gestisce l’intero ciclo di vita dei nodi del piano di controllo, garantendo che il cluster rimanga stabile e ad alta disponibilità.

Come per il bootstrap provider, anche in questo caso abbiamo diverse implementazioni a seconda del caso d’uso.

KubeadmControlPlane Provider

Il KubeadmControlPlane provider utilizza kubeadm per gestire il control plane:

Configurazione dichiarativa:

apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
  name: cluster-control-plane
spec:
  replicas: 3
  version: "v1.29.0"
  kubeadmConfigSpec:
    clusterConfiguration:
      etcd:
        local:
          dataDir: "/var/lib/etcd"
      networking:
        serviceSubnet: "10.96.0.0/16"
        podSubnet: "10.244.0.0/16"

Rolling update strategy:

  • Update sequenziali per mantenere quorum etcd
  • Validation dei componenti prima del prossimo nodo
  • Rollback automatico in caso di failure

TalosControlPlane Provider

Il TalosControlPlane provider offre gestione nativa per Talos Linux:

Vantaggi specifici:

  • Configurazione immutabile via API
  • Upgrade atomici senza downtime
  • Eliminazione di SSH e accesso shell
  • Integration nativa con Talos API

Infrastructure Provider

L’infrastrucure provider è il componente che si occupa di dialogare con le risorse hardware, siano essere cloud o on-premise, con lo scopo di inizializzare le risorse che formeranno il cluster.

A differenza del bootstrap provider e del control plane provider, che si concentrano specificamente sulla configurazione di Kubernetes, l’infrastructure provider si occupa di tutto ciò che sta “sotto” il cluster.

Provider Pattern

Tutti i provider implementano il contratto standard CAPI:

InfraCluster Resource:

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: ProxmoxCluster
spec:
  controlPlaneEndpoint:
    host: "192.168.1.100"
    port: 6443
  ipv4Config:
    addresses: ["192.168.1.100-192.168.1.110"]
    prefix: 24
    gateway: "192.168.1.1"

InfraMachine Resource:

apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
kind: ProxmoxMachine
spec:
  sourceNode: "proxmox-node-01"
  templateID: 8700
  diskSize: "20G"
  memoryMiB: 4096
  numCores: 2

Proxmox Provider

Il Cluster API Provider Proxmox fornisce integrazione nativa con Proxmox VE:

Funzionalità supportate:

  • VM provisioning tramite Proxmox API
  • Template cloning e customization
  • Network configuration automatica
  • Storage management per dischi VM
  • Integration con cloud-init per bootstrap

Custom Resource Definitions (CRDs)

Le CRDs rappresentano il linguaggio dichiarativo di CAPI, permettendo di definire infrastruttura Kubernetes attraverso manifest YAML standard.

Cluster CRD

La risorsa Cluster serve come entry point dichiarativo per definire un cluster Kubernetes completo:

apiVersion: cluster.x-k8s.io/v1beta1
kind: Cluster
metadata:
  name: production-cluster
  namespace: default
spec:
  clusterNetwork:
    services:
      cidrBlocks: ["10.96.0.0/16"]
    pods:  
      cidrBlocks: ["10.244.0.0/16"]
  controlPlaneEndpoint:
    host: "192.168.1.100"
    port: 6443
  controlPlaneRef:
    apiVersion: controlplane.cluster.x-k8s.io/v1beta1
    kind: TalosControlPlane
    name: production-control-plane
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: ProxmoxCluster
    name: production-proxmox

Campi critici:

  • controlPlaneRef: riferimento al provider che gestisce il control plane
  • infrastructureRef: riferimento al provider di infrastruttura
  • clusterNetwork: configurazione di rete del cluster
  • controlPlaneEndpoint: endpoint per l’accesso all’API server

Machine CRD

La risorsa Machine rappresenta l’astrazione di una singola istanza di calcolo destinata a diventare un nodo Kubernetes:

apiVersion: cluster.x-k8s.io/v1beta1
kind: Machine
metadata:
  name: worker-node-01
spec:
  version: "v1.29.0"
  bootstrap:
    configRef:
      apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
      kind: TalosConfig
      name: worker-bootstrap-config
  infrastructureRef:
    apiVersion: infrastructure.cluster.x-k8s.io/v1beta1
    kind: ProxmoxMachine
    name: worker-node-01-proxmox
status:
  phase: "Running"
  addresses:
    - type: "InternalIP"
      address: "192.168.1.101"
  nodeRef:
    kind: "Node"
    name: "worker-node-01"

Principio di immutabilità: Le Machine sono progettate come immutable infrastructure. Modifiche alla specifica richiedono sostituzione completa dell’istanza piuttosto che update in-place.

MachineSet CRD

MachineSet implementa il pattern ReplicaSet per gestire gruppi di Machine identiche:

apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineSet
metadata:
  name: worker-machines
spec:
  replicas: 3
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: "production-cluster"
  template:
    metadata:
      labels:
        cluster.x-k8s.io/cluster-name: "production-cluster"
    spec:
      version: "v1.29.0"
      bootstrap:
        configRef:
          apiVersion: bootstrap.cluster.x-k8s.io/v1beta1
          kind: TalosConfig
          name: worker-bootstrap-config

Funzionalità:

  • Mantiene costante il numero di macchine desiderato
  • Sostiusce macchine in caso di fail
  • Gestisce scale up/down
  • Configurazione basata su template

MachineDeployment CRD

MachineDeployment fornisce update dichiarativi e rolling changes per flotte di Machine:

apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
  name: worker-deployment
spec:
  replicas: 5
  selector:
    matchLabels:
      cluster.x-k8s.io/cluster-name: "production-cluster"
  template:
    # Machine template specification
  strategy:
    type: "RollingUpdate"
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1

Rolling update process:

  1. Crea un nuovo MachineSet con la configurazione aggiornata
  2. Scala il nuovo MachineSet in base alla strategia definita
  3. Riduci il vecchio MachineSet man mano che le nuove macchine diventano pronte
  4. Elimina il vecchio MachineSet al termine della migrazione

Reconciliation Loop e Control Theory

Principi del Control Loop

CAPI implementa il controller pattern di Kubernetes, basato sui principi della teoria del controllo:

┌─────────────┐    ┌──────────────┐    ┌─────────────┐
│   Desired   │───▶│  Controller  │───▶│   Actual    │
│    State    │    │              │    │    State    │
│  (Spec)     │    │              │    │  (Status)   │
└─────────────┘    └──────────────┘    └─────────────┘
       ▲                  ▲                     │
       │                  │                     │
       │            ┌──────────────┐            │
       └────────────│  Feedback    │◀───────────┘
                    │    Loop      │
                    └──────────────┘

Algoritmo di Reconciliation

Ogni controller CAPI implementa la stessa logica base:

func (r *Reconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
    // 1. Observe - Fetch current state
    obj := &v1beta1.Object{}
    if err := r.Get(ctx, req.NamespacedName, obj); err != nil {
        return ctrl.Result{}, client.IgnoreNotFound(err)
    }
    
    // 2. Analyze - Compare desired vs actual state  
    if obj.DeletionTimestamp != nil {
        return r.reconcileDelete(ctx, obj)
    }
    
    // 3. Act - Take corrective action
    return r.reconcileNormal(ctx, obj)
}

Idempotenza e Error Handling

Principi di Idempotenza

Le operazioni CAPI sono progettate per essere idempotenti, permettendo esecuzione sicura multipla:

Esempi di operazioni idempotenti:

  • Provisioning VM: verifica esistenza prima della creazione
  • Configuration update: apply solo se diversa dallo stato corrente
  • Resource cleanup: ignora errori “not found” durante la cancellazione

Gestione Errori e Retry

CAPI implementa strategie di retry sofisticate per gestire errori transienti:

// Exponential backoff per retry
return ctrl.Result{
    Requeue: true,
    RequeueAfter: time.Duration(math.Pow(2, float64(retryCount))) * time.Second,
}, nil

Categorie di errori:

  • Transient errors: network timeouts, temporary API unavailability
  • Configuration errors: invalid specifications, missing resources
  • Infrastructure errors: quota exceeded, hardware failures

Flusso End-to-End: Da Manifest a Cluster

Phase 1: Resource Creation

kubectl apply -f cluster-manifest.yaml

Sequenza di eventi:

  1. API Server: valida e persiste le risorse nel cluster
  2. CAPI Core Controller: rileva nuova risorsa Cluster
  3. Admission Controllers: applicano policies e defaults
  4. Event Recording: registra eventi per debugging

Phase 2: Infrastructure Provisioning

Cluster Controller ──→ Infrastructure Provider ──→ Proxmox API
      │                        │                        │
      │                        ▼                        ▼
      │              ProxmoxCluster Created    VM Template Cloned
      │                        │                        │
      ▼                        ▼                        ▼
  Status Update        Infrastructure Ready      VM Started

Attività del Proxmox Provider:

  • Clone VM template per ogni machine
  • Configure network interfaces
  • Inject cloud-init configuration
  • Start VM instances
  • Update ProxmoxMachine status

Phase 3: Bootstrap Process

Machine Controller ──→ Bootstrap Provider ──→ TalosConfig Generation
      │                       │                        │
      │                       ▼                        ▼
      │              Cloud-Init Generated      Config Applied to VM
      │                       │                        │
      ▼                       ▼                        ▼
  Bootstrap Ready       Node Joins Cluster    Kubernetes Ready

Bootstrap Provider activities:

  • Genera configurazioni node-specific
  • Genera token di join e certificati
  • Configura prametri kubelet
  • Setup container runtime
  • Applica policy di sicurezza

Phase 4: Control Plane Initialization

Per control plane nodes, il processo include passaggi aggiuntivi:

  1. Primo nodo: inizializza cluster etcd
  2. Genera certificati per il cluster
  3. Avvia API server, controller-manager, scheduler
  4. Nodi successivi: join al cluster esistente
  5. Configura endpoint per il load balancer

Phase 5: Kubeconfig Generation

Una volta che l’API server è accessibile viene generato, all’interno del management cluster, un secret che contiene il kubeconfig necessario per connettersi al workload cluster:

// Controller genera kubeconfig
kubeconfig := &corev1.Secret{
    ObjectMeta: metav1.ObjectMeta{
        Name: fmt.Sprintf("%s-kubeconfig", cluster.Name),
        Namespace: cluster.Namespace,
    },
    Data: map[string][]byte{
        "value": kubeconfigBytes,
    },
}

Contenuto kubeconfig:

  • Certificate Authority del cluster
  • Client certificate per admin access
  • API server endpoint configuration
  • Context configuration per kubectl

Debugging e Resouce Inspection

Monitoring Controller Health

# Check controller pod status
kubectl get pods -n capi-system
kubectl get pods -n capx-system  # Infrastructure provider
kubectl get pods -n capi-bootstrap-talos-system

# Review controller logs
kubectl logs -n capi-system deployment/capi-controller-manager
kubectl logs -n capx-system deployment/capx-controller-manager

Resource Status Inspection

# Check cluster status
kubectl get cluster production-cluster -o wide

# Examine machine lifecycle
kubectl get machines -A -o wide

# Review events for troubleshooting
kubectl describe cluster production-cluster
kubectl get events --sort-by='.lastTimestamp' -A

Common Debugging Patterns

Infrastructure provisioning failures:

# Check infrastructure resources
kubectl get proxmoxclusters,proxmoxmachines -A -o wide
kubectl describe proxmoxmachine <machine-name>

# Verify Proxmox connectivity
curl -k -H "Authorization: PVEAPIToken=$PROXMOX_TOKEN=$PROXMOX_SECRET" \
     "$PROXMOX_URL/version"

Bootstrap failures:

# Examine bootstrap configuration
kubectl get talosconfigs -A -o yaml
kubectl describe talosconfig <config-name>

# Check cloud-init logs on VM
# (requires VM console access)
tail -f /var/log/cloud-init-output.log

L’architettura modulare di CAPI, basata su controller specializzati e CRDs estensibili, fornisce un framework robusto per gestire cluster Kubernetes su qualsiasi infrastruttura. La comprensione di questi componenti e dei loro pattern di interazione è fondamentale per implementazioni production-ready.

Per approfondimenti sull’implementazione dei controller custom e l’estensione di CAPI, consultare la Developer Guide e il Kubebuilder Book.

La prossima parte esplorerà Talos Linux e la sua integrazione nativa con CAPI, mostrando come l’OS immutabile semplifichi la gestione dei nodi Kubernetes.