Skip to main content
Using make run moves the operator’s brain from a pod in the cluster to a process on your workstation while it still manipulates real cluster objects. This gives you a fast, interactive workbench to iterate on reconcile logic before you package or deploy anything. The cluster is the building; the controller is the technician with a radio. In production the technician works inside the building (as a pod). During local development the technician sits at your desk, but
The image compares "In Production" with "Local dev" environments, showing a technician working inside a pod in production and a stick figure holding a tool on a table.
the radio still reaches the building. The API server is that radio link: Deployments, Services, ConfigMaps and other web app resources remain real cluster objects that your locally-run controller reads and modifies.
The image shows a schematic of a building labeled "Cluster" with icons representing different components and text indicating "The Objects Are Still Real" and "Real objects, not mocked."
Why use local mode? It shortens the edit → run → observe loop:
  • Stop the manager.
  • Change the code.
  • Start the manager locally.
  • Apply a WebApp resource.
  • Observe what the controller does.
This is the quickest way to answer: did my reconcile logic behave the way I expect? Before the controller can act on a custom resource, the API server must know the resource schema. make install applies the CustomResourceDefinition (CRD) for the WebApp type so the API server recognizes it. If the CRD is not installed, the cluster cannot understand the object you want to watch even if your controller is running.
Think of the manager as a local process that hosts your controller and talks to the API server using the kubeconfig on your machine. To the cluster it is just another API client; to you it is an easily stoppable, restartable, and observable process. Use the following quick-reference to map steps to their intent: When running locally, you will typically check the manager output in your terminal (where make run runs) and use kubectl get to inspect resource state. For cluster-side evidence, use kubectl (for example kubectl get webapp -A) and for in-cluster components inspect Pod logs once you deploy the packaged controller.
Use local mode for fast feedback on reconcile logic and resource reads/writes. Treat it as a development workbench: quick, iterative testing to validate behavior before you move on to packaging and in-cluster validation.
Local mode is powerful, but it has limits. It can validate reconcile behavior, confirm reads and writes against real objects, and produce log evidence. It cannot prove final production concerns such as the exact deployment shape, service account permission boundaries (your kubeconfig user can be more privileged than the controller’s in-cluster identity), leader election behavior, webhook admission controllers, or production networking and RBAC interactions.
The image lists the capabilities and limitations of local mode, highlighting what it can and cannot prove about system behavior. It includes items like reconciled behavior, object reads and writes, and log evidence on the left, while limitations such as final deployment shape and service account permissions are noted on the right.
Those checks belong in subsequent stages of testing and CI. For now, use local mode for what it does best: rapid iteration and evidence-driven debugging. Later, the workbench output becomes the raw material for deeper debugging, packaging, and production verification.

Watch Video