> ## Documentation Index
> Fetch the complete documentation index at: https://notes.kodekloud.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Demo Installing With Make Deploy

> Deploying a Kubernetes operator using make deploy to set the image via Kustomize, apply CRDs, RBAC, Service and Deployment, then verify rollout and CRD registration

The operator image has been pushed. The next step is to install the in-cluster manifests that reference that image: a CustomResourceDefinition (CRD), RBAC roles/bindings, a Service for metrics, and the controller Deployment. The operator scaffold's Makefile provides a `deploy` target that generates and applies these manifests, using the `IMG` variable to set the controller image used by Kustomize.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/_cG0RWHUHqfjYKx0/images/Kubernetes-Operators/Packaging-And-Distribution/Demo-Installing-With-Make-Deploy/installing-with-make-deploy-demo.jpg?fit=max&auto=format&n=_cG0RWHUHqfjYKx0&q=85&s=6ad4b5e597c882a645337ad8f87456df" alt="The image is a slide titled &#x22;Installing With Make Deploy,&#x22; featuring a large dark blue shape on the right with the word &#x22;Demo.&#x22; It includes a copyright notice for KodeKloud." width="1920" height="1080" data-path="images/Kubernetes-Operators/Packaging-And-Distribution/Demo-Installing-With-Make-Deploy/installing-with-make-deploy-demo.jpg" />
</Frame>

## Key Makefile fragments

Top of the Makefile (trimmed) defines the default image and the container tooling:

```makefile theme={null}
# Image URL to use for all build/push image targets
IMG ?= controller:latest

# Get the currently used golang install path (in GOPATH/bin, unless GOBIN is set)
ifeq (, $(shell go env GOBIN))
GOBIN := $(shell go env GOPATH)/bin
else
GOBIN := $(shell go env GOBIN)
endif

# CONTAINER_TOOL defines the container tool to be used for building images (e.g. docker, podman)
CONTAINER_TOOL ?= docker
```

Inspect the `deploy` target — the important step is `kustomize edit set image`, which updates the manager image in `config/manager` before building and applying the customized manifests:

```makefile theme={null}
.PHONY: deploy
deploy: manifests kustomize ## Deploy controller to the K8s cluster specified in ~/.kube/config.
	cd config/manager && "$(KUSTOMIZE)" edit set image controller=${IMG}
	"$(KUSTOMIZE)" build config/default | "$(KUBECTL)" apply -f -
```

<Callout icon="lightbulb" color="#1CB2FE">
  Always pass the exact `IMG` value to `make deploy` that you used when building and pushing the image. If `IMG` is omitted or incorrect, the generated Deployment can reference a placeholder image and your pods may fail to pull.
</Callout>

## Run make deploy

Set `IMG` to the registry image you pushed and run `make deploy`. The Make target generates CRDs and RBAC, updates the manager image in Kustomize, builds the final manifests, and applies them to the cluster.

```bash theme={null}
export IMG="127.0.0.1:5000/course/webapp-operator:v0.1.0"
printenv IMG
make deploy IMG="$IMG"
```

Example trimmed output showing resources being created:

```bash theme={null}
clusterrole.rbac.authorization.k8s.io/webapp-operator-metrics-reader created
clusterrole.rbac.authorization.k8s.io/webapp-operator-webapp-admin-role created
rolebinding.rbac.authorization.k8s.io/webapp-operator-leader-election-rolebinding created
clusterrolebinding.rbac.authorization.k8s.io/webapp-operator-manager-rolebinding created
service/webapp-operator-controller-manager-metrics-service created
deployment.apps/webapp-operator-controller-manager created
```

If the image reference is wrong or your cluster cannot pull from the registry, pod events will typically show `ImagePullBackOff` or similar error messages.

<Callout icon="warning" color="#FF6B6B">
  Ensure the registry referenced by `IMG` is accessible from the cluster nodes (network and authentication). Private registries often require imagePullSecrets or registry credentials configured on the nodes.
</Callout>

## Verify rollout and controller readiness

Wait for the controller manager Deployment to roll out. A successful rollout means the controller pod was created and its manager container became ready.

```bash theme={null}
kubectl -n webapp-operator-system rollout status deploy/webapp-operator-controller-manager --timeout=180s
kubectl get pods -n webapp-operator-system
# NAME                                                   READY   STATUS    RESTARTS   AGE
# webapp-operator-controller-manager-566cd8df5c-tsb9x    1/1     Running   0          38s
```

The controller is now running in-cluster as a Pod (not via `make run`). Inspect its logs to confirm it became leader and started workers:

```bash theme={null}
kubectl -n webapp-operator-system logs deploy/webapp-operator-controller-manager
```

Typical startup log lines include leader election, metrics server binding, and controller startup, for example:

```bash theme={null}
2026-06-15T19:45:41Z DEBUG events ... became leader  {"type":"Normal", ... "reason":"LeaderElection"}
2026-06-15T19:45:42Z INFO  controller-runtime.metrics Serving metrics server {"bindAddress":":8443","secure":true}
2026-06-15T19:45:41Z INFO  Starting Controller {"controller":"webapp","controllerGroup":"webapp.kodekloud.com"}
```

Worker startup indicates the controller runtime is ready to reconcile WebApp resources.

## Confirm the CRD is registered

Verify the API server now understands the `webapp` custom resource:

```bash theme={null}
kubectl get crd webapps.webapp.kodekloud.com

# NAME                            CREATED AT
# webapps.webapp.kodekloud.com    2026-06-15T19:45:40Z
```

A present CRD proves the cluster can accept WebApp objects and the in-cluster controller can reconcile them.

## Quick reference: what `make deploy` creates

| Resource type                                           | Purpose                                                    | Example / note                                       |
| ------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------- |
| CRD                                                     | Adds the `WebApp` API to the cluster                       | `webapps.webapp.kodekloud.com`                       |
| RBAC (Role/ClusterRole, RoleBinding/ClusterRoleBinding) | Grants permissions to the controller                       | Roles like `webapp-operator-webapp-admin-role`       |
| Service                                                 | Exposes metrics for scraping                               | `webapp-operator-controller-manager-metrics-service` |
| Deployment                                              | Runs the controller manager Pod using the image from `IMG` | `webapp-operator-controller-manager`                 |

## Summary / Checklist

* Build and push your operator image to a registry reachable by the cluster.
* Use the same image reference when running `make deploy` via `IMG`.
* `make deploy` updates the Kustomize manager image, builds manifests, and applies them.
* Wait for the Deployment rollout and confirm the controller Pod is Running.
* Check controller logs for leader election and worker startup messages.
* Verify the CRD exists so custom resources can be created and reconciled.

## Links and references

* [Kustomize documentation](https://kubectl.docs.kubernetes.io/references/kustomize/)
* [kubectl reference](https://kubernetes.io/docs/reference/kubectl/)
* [Kubernetes CRD concepts](https://kubernetes.io/docs/tasks/extend-kubernetes/custom-resources/custom-resource-definitions/)

<CardGroup>
  <Card title="Watch Video" icon="video" cta="Learn more" href="https://learn.kodekloud.com/user/courses/kubernetes-operators/module/5a9bfe56-bc26-4325-b659-06027d4e815f/lesson/c25b009f-0952-4fdb-8dbc-e57ade3dfc37" />

  <Card title="Practice Lab" icon="flask-conical" cta="Learn more" href="https://learn.kodekloud.com/user/courses/kubernetes-operators/module/5a9bfe56-bc26-4325-b659-06027d4e815f/lesson/9b287938-25fd-40eb-990d-13e36b711ef2" />
</CardGroup>
