> ## 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.

# Section Overview

> Guide to packaging and distributing a Kubernetes operator by building and pushing the controller image, deploying install manifests, verifying the in-cluster manager, and introducing Operator Lifecycle Manager

Up to this point you've been developing and testing the web app Operator primarily from a developer workflow: running the manager locally, watching reconciliation logs, adding status and finalizers, implementing CEL validation, and validating behavior inside a Kubernetes cluster.

This lesson shifts the focus from "does the operator work?" to "how do other people install and run it?" In other words: how do you package the controller into a container image, publish it, and deliver repeatable install manifests so others (and CI/CD systems) can deploy and run the operator in their clusters?

Packaging begins with the controller image. The operator manager is a Go binary, but Kubernetes runs containers. Kubebuilder scaffolds a Dockerfile that builds the manager and copies the compiled binary into a lightweight runtime image. Your tasks in this section are:

* Inspect the Dockerfile build path and verify the binary ends up in the runtime image.
* Connect the image tag you produce to the Deployment used by the operator manager.
* Use the provided Makefile targets (scaffolded by Kubebuilder) to build, push, and deploy the operator.

Key Makefile targets you will use:

| Target              | Purpose                                                                                                                | Example                                                           |
| ------------------- | ---------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- |
| `make docker-build` | Build the OCI image using the `IMG` value you provide.                                                                 | `make docker-build IMG=myregistry.example.com/webapp-operator:v1` |
| `make docker-push`  | Push the tagged image to the configured registry so clusters can pull it.                                              | `make docker-push IMG=myregistry.example.com/webapp-operator:v1`  |
| `make deploy`       | Run the configured Kustomize build and apply CRDs, RBAC, the manager Deployment, Service, and other install resources. | `make deploy IMG=myregistry.example.com/webapp-operator:v1`       |

Example workflow (end-to-end):

```bash theme={null}
# 1) Build the image with an explicit image reference (include registry and tag)
make docker-build IMG=myregistry.example.com/webapp-operator:v1

# 2) Push the image so the cluster can pull it
make docker-push IMG=myregistry.example.com/webapp-operator:v1

# 3) Apply the install manifests (Kustomize build + kubectl apply)
make deploy IMG=myregistry.example.com/webapp-operator:v1
```

IMG is not cosmetic — the exact image reference you set becomes part of the generated install manifests (the container image field in the manager Deployment). If you set an incorrect `IMG` the cluster may pull the wrong image or the controller may fail to start.

After deploying, verify the controller manager is running and is using the image you pushed:

```bash theme={null}
# Confirm the Deployment exists and shows the expected image
kubectl -n <namespace> get deployment webapp-operator-controller-manager -o yaml | grep image

# Check pods and logs
kubectl -n <namespace> get pods
kubectl -n <namespace> logs deploy/webapp-operator-controller-manager -c manager
```

Finally, create a WebApp custom resource and confirm the installed operator reconciles it from inside the cluster — the same behavior you validated locally should now occur with the controller running as a Kubernetes workload.

<Frame>
  <img src="https://mintcdn.com/kodekloud-c4ac6d9a/_cG0RWHUHqfjYKx0/images/Kubernetes-Operators/Packaging-And-Distribution/Section-Overview/the-lab-ship-it-end-to-end.jpg?fit=max&auto=format&n=_cG0RWHUHqfjYKx0&q=85&s=cecf9f3d088255c40a2b8f9b09e1e33d" alt="The image displays a three-step process titled &#x22;The Lab: Ship It End to End,&#x22; which includes building/using an image, deploying manifests, and verifying the controller manager running, each marked as complete." width="1920" height="1080" data-path="images/Kubernetes-Operators/Packaging-And-Distribution/Section-Overview/the-lab-ship-it-end-to-end.jpg" />
</Frame>

This section closes with a brief look at Operator Lifecycle Manager (OLM). OLM is not required for every operator deployment, but it's important to understand its model: bundles, ClusterServiceVersions (CSVs), catalogs, and subscriptions. Raw manifests or a kustomize-based install are sufficient for many environments; OLM becomes valuable when you need install metadata, upgrade channels, and marketplace-style distribution.

By the end of this section you will have a repeatable packaging and deployment path for the web app Operator: a container image, published install manifests, a verified manager running in-cluster, and an upgrade story you can use going forward.

<Callout icon="lightbulb" color="#1CB2FE">
  When using the Makefile targets, always set `IMG` to the exact image reference you intend to deploy (including registry and tag). The deployed manifests will reference that value, so an incorrect `IMG` will cause the cluster to pull a different image or fail to start the controller.
</Callout>

<Callout icon="warning" color="#FF6B6B">
  Ensure you have credentials and write access to the target registry before running `make docker-push`. Also confirm the cluster can pull from that registry (private registries may require imagePullSecrets).
</Callout>

## References

* Kubebuilder: [https://book.kubebuilder.io/](https://book.kubebuilder.io/)
* Kustomize: [https://kustomize.io/](https://kustomize.io/)
* Operator Lifecycle Manager (OLM): [https://olm.operatorframework.io/](https://olm.operatorframework.io/)

<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/f81893d3-e35e-4a4a-a360-ab8e27c866e4" />
</CardGroup>
