Skip to content

OCM with KinD

A containerlab topology that deploys 3 KinD clusters — 1 hub + 2 spokes — for experimenting with Open Cluster Manager using the clusteradm CLI.

Topology

graph TD
  subgraph Docker_Host["Docker Host"]
    subgraph KinD["KinD Clusters — kindest/node:v1.31.0"]
      hub["🟢 hub (Control Plane)<br/>cluster-manager<br/>API :6443"]
      spoke1["🔵 spoke1 (Worker)<br/>klusterlet<br/>API :6443"]
      spoke2["🔵 spoke2 (Worker)<br/>klusterlet<br/>API :6443"]
    end
    hub---|"Docker bridge<br/>172.18.0.0/16"| spoke1
    hub---|"Docker bridge<br/>172.18.0.0/16"| spoke2
  end

  classDef hub fill:#1b5e20,color:#fff,stroke:#2e7d32
  classDef spoke fill:#0d47a1,color:#fff,stroke:#1565c0
  class hub hub
  class spoke1,spoke2 spoke

Containerlab generates a live SVG graph from this topology at clab-ocm-demo/graph/.

Prerequisites

Tool Minimum Version Purpose
containerlab 0.50+ Deploys KinD nodes as Docker containers
Docker 24+ Container runtime for KinD
kubectl 1.28+ Kubernetes CLI
clusteradm 1.3+ OCM bootstrapping

Quick Start

# From the ocm/ directory:

# Full automated pipeline:
make demo

# Or step by step:
make deploy          # Spin up 3 KinD clusters + export kubeconfigs
make install-ocm     # Initialize OCM hub via clusteradm init
make register-spokes # Register spokes via clusteradm join
make accept          # Accept managed clusters via clusteradm accept

Make Targets

Target Description
deploy Deploy the 3-cluster KinD topology + export kubeconfigs
destroy Tear down the lab
status Show containerlab node status
kubeconfigs (Re-)export kubeconfigs to ./kubeconfigs/
install-ocm Initialize OCM hub via clusteradm init
register-spokes Register spoke clusters via clusteradm join
accept Approve pending spoke CSRs via clusteradm accept
demo Full pipeline: deploy → OCM hub → register → accept
clean Destroy + clean kubeconfigs

Manual Inspection

# Point to the hub cluster
export KUBECONFIG=./kubeconfigs/hub

# List managed clusters
kubectl get managedclusters

# Deploy a workload to a spoke via ManifestWork
cat <<EOF | kubectl apply -f -
apiVersion: work.open-cluster-management.io/v1
kind: ManifestWork
metadata:
  name: hello-ocm
  namespace: spoke1
spec:
  workload:
    manifests:
      - apiVersion: v1
        kind: Namespace
        metadata:
          name: ocm-demo
      - apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: nginx
          namespace: ocm-demo
        spec:
          replicas: 1
          selector:
            matchLabels:
              app: nginx
          template:
            metadata:
              labels:
                app: nginx
            spec:
              containers:
                - name: nginx
                  image: nginx:alpine
EOF

# Verify on spoke
export KUBECONFIG=./kubeconfigs/spoke1
kubectl get pods -n ocm-demo

Lab Details

  • Topology file: topology.clab.yml
  • Kubeconfigs: Exported to ./kubeconfigs/{hub,spoke1,spoke2}
  • Node images: kindest/node:v1.31.0
  • Management network: 172.18.0.0/16 (Docker bridge)