Examples
Run dfmicro as a normal user after creating its sudoers rules. The examples assume a MicroShift image, ~/pull.json, and ~/idms.yaml are available.
Prepare access
dfmicro ops sudoers create
Inspect the CLI build and embedded defaults.
The examples below were verified with this build and configuration:
$ dfmicro -v
dfmicro version dev (none, 2026-10-11T07:14:30Z)
$ dfmicro config
{
"name": "micro",
"image": "ghcr.io/leelavg/microshift:5.0.0_202609201132_g4582bf673_5.0.0_okd_scos.ec.8",
"powerTuning": true,
"apiServerPort": 6443,
"clusterCIDR": "10.42.0.0/16",
"serviceCIDR": "10.43.0.0/16",
"exposeKubeAPI": true,
"lvmVolSize": "10G",
"overprovisionRatio": 20,
"shareHostContainers": true,
"enableThinpool": true,
"enableTopoLVM": true,
"useEtcd": false,
"bridgeName": "micro",
"bridgeSubnet": "172.20.0.0/24",
"groupCount": 5,
"clustersPerGroup": 5,
"reservePerGroup": 5,
"nadNamespace": "default"
}
Create and inspect a cluster
dfmicro cluster create \
--name demo \
--no-topolvm \
--pull-secret ~/pull.json \
--idms ~/idms.yaml
dfmicro cluster list
dfmicro cluster config --name demo
dfmicro node config --cluster demo
dfmicro cluster kubeconfig --name demo >/tmp/demo-kubeconfig
export KUBECONFIG=/tmp/demo-kubeconfig
kubectl get nodes -o wide
kubectl get pods -A
Stop and start the cluster without removing its state.
dfmicro cluster stop --name demo
dfmicro cluster start --name demo
Add and remove a worker
Add a worker after the control plane is ready. The command checks control-plane readiness before onboarding the worker.
dfmicro node add --cluster demo
kubectl get nodes -o wide
kubectl get pods -A -o wide
sudo podman exec demo-2 journalctl -u microshift --no-pager
Add explicit mounts to a worker when it needs storage not present in the cluster creation mounts.
dfmicro node add --cluster demo --mount /host/path:/worker/path:ro
Use --force when debugging worker onboarding and the pre-add readiness check is not desired.
dfmicro node add --cluster demo --force
Remove a worker and add another one to reuse the freed slot.
dfmicro node remove --cluster demo --name demo-2
dfmicro node add --cluster demo
kubectl get nodes -o wide
Create an etcd-backed cluster
dfmicro cluster create \
--name etcd-demo \
--etcd \
--no-topolvm \
--pull-secret ~/pull.json \
--idms ~/idms.yaml
dfmicro node add --cluster etcd-demo
dfmicro cluster kubeconfig --name etcd-demo >/tmp/etcd-demo-kubeconfig
KUBECONFIG=/tmp/etcd-demo-kubeconfig kubectl get nodes
Peer two clusters
Use distinct pod and service CIDRs when testing peer operations.
dfmicro cluster create \
--name net-a \
--no-topolvm \
--api-server-port 6443 \
--cluster-cidr 10.42.0.0/16 \
--service-cidr 10.43.0.0/16 \
--pull-secret ~/pull.json \
--idms ~/idms.yaml
dfmicro cluster create \
--name net-b \
--no-topolvm \
--api-server-port 6444 \
--cluster-cidr 10.52.0.0/16 \
--service-cidr 10.53.0.0/16 \
--pull-secret ~/pull.json \
--idms ~/idms.yaml
dfmicro network peer --cluster net-a --cluster net-b
dfmicro network unpeer --cluster net-a --cluster net-b
Attach clusters to a shared secondary network
Create one Podman bridge and connect both clusters to it. The secondary network uses its own subnet and does not replace the cluster or service networks.
dfmicro network create --name backbone --subnet 172.30.0.0/16
dfmicro network connect --cluster net-a --cluster net-b --to backbone
dfmicro network attach \
--cluster net-a:group1 \
--cluster net-b:group1 \
--to backbone \
--multi-node
With --multi-node, the attachment uses Whereabouts IPAM and enables it on the cluster nodes. Whereabouts must already be installed in the clusters.
Deploy a diagnostic pod in each cluster and inspect the assigned secondary addresses.
dfmicro cluster kubeconfig --name net-a >/tmp/net-a-kubeconfig
dfmicro cluster kubeconfig --name net-b >/tmp/net-b-kubeconfig
kubectl --kubeconfig /tmp/net-a-kubeconfig apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: netshoot-a
annotations:
k8s.v1.cni.cncf.io/networks: default/backbone-group1
spec:
containers:
- name: netshoot
image: docker.io/nicolaka/netshoot:v0.16
command: ["sleep", "infinity"]
securityContext:
capabilities:
add: ["NET_RAW"]
EOF
kubectl --kubeconfig /tmp/net-b-kubeconfig apply -f - <<'EOF'
apiVersion: v1
kind: Pod
metadata:
name: netshoot-b
annotations:
k8s.v1.cni.cncf.io/networks: default/backbone-group1
spec:
containers:
- name: netshoot
image: docker.io/nicolaka/netshoot:v0.16
command: ["sleep", "infinity"]
securityContext:
capabilities:
add: ["NET_RAW"]
EOF
kubectl --kubeconfig /tmp/net-a-kubeconfig get pod netshoot-a -o wide
kubectl --kubeconfig /tmp/net-b-kubeconfig get pod netshoot-b -o wide
Inspect and remove the attachment when finished.
kubectl --kubeconfig /tmp/net-a-kubeconfig delete pod netshoot-a --grace-period=10
kubectl --kubeconfig /tmp/net-b-kubeconfig delete pod netshoot-b --grace-period=10
dfmicro network config --name backbone
dfmicro network detach --cluster net-a:group1 --cluster net-b:group1 --from backbone
dfmicro network disconnect --cluster net-a --cluster net-b --from backbone
dfmicro network delete --name backbone
Configure ODF storage topologies
These examples assume the clusters have already been created. Add workers to a provider before configuring it as a multi-node provider.
Load the host kernel modules before installing ODF operators. The image below is an example tag. Replace it with an image available to your environment.
dfmicro addon odf modules load
Single-node ODF
Install and configure ODF on an existing single-node cluster:
dfmicro addon odf --cluster standalone install \
--catalog-image quay.io/example/odf-operator-catalog:v5.0 \
--channel stable-5.0 --version 5.0.0
dfmicro addon odf --cluster standalone configure
dfmicro cluster kubeconfig --name standalone >/tmp/standalone-kubeconfig
kubectl --kubeconfig /tmp/standalone-kubeconfig get storagecluster -n openshift-storage
kubectl --kubeconfig /tmp/standalone-kubeconfig get storageclass
Rook Ceph provider with an external ODF consumer
Install the Rook operator on provider and the ODF operator on consumer:
dfmicro addon odf --cluster provider install \
--catalog-image quay.io/example/odf-operator-catalog:v5.0 \
--channel stable-5.0 --version 5.0.0 --sub-name rook-ceph-operator
dfmicro addon odf --cluster consumer install \
--catalog-image quay.io/example/odf-operator-catalog:v5.0 \
--channel stable-5.0 --version 5.0.0 --sub-name odf-operator
Configure Rook on provider, then connect consumer to it:
dfmicro addon odf --cluster provider configure --external-ceph
dfmicro addon odf --cluster consumer configure --connect-to provider
dfmicro cluster kubeconfig --name provider >/tmp/provider-kubeconfig
dfmicro cluster kubeconfig --name consumer >/tmp/consumer-kubeconfig
kubectl --kubeconfig /tmp/provider-kubeconfig get cephcluster -n openshift-storage
kubectl --kubeconfig /tmp/consumer-kubeconfig get storagecluster -n openshift-storage
ODF provider with a client-only consumer
Install the ODF operator on provider and the client operator on consumer:
dfmicro addon odf --cluster provider install \
--catalog-image quay.io/example/odf-operator-catalog:v5.0 \
--channel stable-5.0 --version 5.0.0 --sub-name odf-operator
dfmicro addon odf --cluster consumer install \
--catalog-image quay.io/example/odf-operator-catalog:v5.0 \
--channel stable-5.0 --version 5.0.0 --sub-name ocs-client-operator
Configure the provider for host networking and multiple nodes, then onboard the client-only consumer:
# Host-networked Ceph MONs need separate nodes, so use at least three nodes.
dfmicro addon odf --cluster provider configure --hostnetwork --multi-node
dfmicro addon odf --cluster consumer configure --client --connect-to provider
dfmicro cluster kubeconfig --name provider >/tmp/provider-kubeconfig
dfmicro cluster kubeconfig --name consumer >/tmp/consumer-kubeconfig
kubectl --kubeconfig /tmp/provider-kubeconfig patch storageconsumer consumer \
-n openshift-storage --type=json \
-p '[{"op":"add","path":"/spec/storageClasses","value":[{"name":"ocs-storagecluster-ceph-rbd"}]}]'
kubectl --kubeconfig /tmp/consumer-kubeconfig get storageclass
Create workloads in consumer using the published ocs-storagecluster-ceph-rbd
StorageClass to verify client-side provisioning and access.
Clean up
dfmicro cluster rm --name demo
dfmicro cluster rm --name etcd-demo
dfmicro cluster rm --name net-a
dfmicro cluster rm --name net-b