024 Project 24: Controller Pattern Simulator

024 Build a Controller/Reconciler Simulator

Practice the Kubernetes-style reconciliation loop without Kubernetes dependencies.

desired state + actual state -> reconcile loop -> actions -> converge

Full main.go

package main

import (
    "fmt"
    "math/rand"
    "time"
)

type State struct {
    DesiredReplicas int
    ActualReplicas  int
}

func reconcile(s *State) string {
    if s.ActualReplicas < s.DesiredReplicas {
        s.ActualReplicas++
        return "scale up"
    }
    if s.ActualReplicas > s.DesiredReplicas {
        s.ActualReplicas--
        return "scale down"
    }
    return "noop"
}

func main() {
    rand.Seed(time.Now().UnixNano())
    s := State{DesiredReplicas: 3, ActualReplicas: 0}

    for i := 0; i < 20; i++ {
        if rand.Intn(6) == 0 {
            // simulate external drift
            s.ActualReplicas += rand.Intn(3) - 1
            if s.ActualReplicas < 0 {
                s.ActualReplicas = 0
            }
        }
        action := reconcile(&s)
        fmt.Printf("tick=%02d desired=%d actual=%d action=%s\n", i, s.DesiredReplicas, s.ActualReplicas, action)
        time.Sleep(300 * time.Millisecond)
    }
}

Run

go run .

Step-by-Step Explanation

  1. Model desired and actual state explicitly.
  2. Compute a minimal diff.
  3. Apply one idempotent reconciliation step.
  4. Observe updated state and repeat.
  5. Keep loops convergent and failure-aware.

Code Anatomy

  • State model captures control-plane truth.
  • Reconcile function decides next action.
  • Loop executes continuously with visibility into actions.

Learning Goals

  • Learn the controller pattern used in modern platforms.
  • Build robust automation through repeated reconciliation.
  • Understand convergence over one-shot scripting.