Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

iTechGuides is reader-supported. When you buy through links on our site, we may earn an affiliate commission. As an Amazon Associate I earn from qualifying purchases. Learn more

Building a first Kubernetes controller in Java means writing a program that watches Kubernetes API objects and repeatedly reconciles what exists with the state someone has declared. For a Java project, the Java Operator SDK (JOSDK) is a supported higher-level framework built on the Fabric8 Kubernetes Client; neither is required by Kubernetes. Start with a small, clearly observable behavior, then choose whether you need a custom resource and the operator machinery around it.

What a Kubernetes controller does

A controller is an API client that observes Kubernetes objects and works toward a desired state. It does not normally run once and finish: changes, retries, or later observations can cause its reconciliation logic to run again. The goal is convergence—after repeated runs, actual state matches the desired state as closely as the controller can make it.

For example, a custom resource might declare an application’s desired replica count. A controller reads that declaration and creates or updates a built-in Deployment accordingly. Kubernetes calls the combination of a custom resource definition (CRD), controller code, and its container image an operator when it packages domain-specific operational behavior in this way. The terms are often used loosely: a controller can also manage built-in Kubernetes resources without defining a custom resource.

What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Kubernetes does not mandate Java, JOSDK, or any particular client library. Its operator pattern documentation describes the general model and notes that controllers commonly run outside the control plane, including as a Deployment in the cluster.

Choose the smallest useful first project

Pick behavior whose desired and actual states are easy to see. A good first exercise might ensure that a named ConfigMap exists with specified data, or ensure that a Deployment has the replica count declared by a custom resource. Avoid starting with a controller that manages many resource types, external systems, or complex lifecycle actions.

Decide whether users need a new Kubernetes API object to express the desired state. If an existing built-in object already expresses it, a controller for that resource can be a valid learning project. A CRD makes sense when you need a domain-specific object and fields that Kubernetes users can create and inspect. JOSDK supports controllers for standard resources as well as custom resources, as described in its features documentation.

Choose a Java implementation level

JOSDK and Fabric8 are not competing client ecosystems: JOSDK uses Fabric8 as its Kubernetes client foundation. The practical choice is how much controller lifecycle machinery and convention you want to adopt.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Approach What it provides Trade-off
Java Operator SDK (JOSDK) A controller runtime and higher-level operator features, including event handling, dependent resources, retries, scheduling, error handling, and testing support, according to the project repository. Less lifecycle and reconciliation machinery to assemble yourself, in exchange for learning JOSDK’s abstractions and conventions.
Fabric8 Kubernetes Client directly A Java client for Kubernetes API interactions, with configuration options and a mock server documented in the Fabric8 project repository. More direct control over API interactions, but you take responsibility for more of the controller runtime and reconciliation lifecycle.
Kubernetes Java Client The Java client listed in the Kubernetes API access documentation. Evaluate its current supported Kubernetes versions, required APIs, project conventions, and the operator runtime support you need. The cited documentation points to client releases for support information; it does not establish a version compatibility matrix here.

For a first operator-style project, JOSDK is a natural place to start if you want framework support for reconciliation and related lifecycle concerns. Choose a direct client approach if the goal is to learn lower-level API interactions or to retain more control. In either case, use the current project release documentation to select compatible dependencies; do not combine versions copied from unrelated examples.

Shape the resource API and CRD

If the project uses a custom resource, define its API before implementing the controller. Keep the first spec small: include only the fields needed to express desired state, and decide what valid values look like. Use status for information the controller observes or reports, rather than treating it as another user-owned input.

You can author and review a CRD manifest directly, or generate one from annotated Java resource classes. JOSDK documents CRD generation through Fabric8’s crd-generator-apt; generated manifests are placed under target/classes/META-INF/fabric8. The documentation notes that users of the JOSDK Quarkus extension do not need to add that dependency separately. Check generated output into or package it with your deployment artifacts according to your project’s release process, and review it as an API artifact rather than assuming generated output is automatically correct.

Implement reconciliation as repeatable work

In JOSDK, the central unit is a reconciler: code that receives the resource being reconciled and makes progress toward its desired state. The Reconciler API documentation states, “The implementation of this operation is required to be idempotent.” In practice, repeated calls with the same desired state should converge on the same result instead of creating duplicate resources or repeating harmful side effects.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
  1. Read the resource and relevant state. Use the watched resource’s specification as desired state, then inspect the dependent objects or other state that matters to the behavior.
  2. Compare desired and actual state. Determine what is missing or different before making changes. Avoid unconditional create operations that fail or duplicate work when an object already exists.
  3. Make only necessary changes. Create, update, or delete dependent resources so that another reconciliation can safely run. Treat external side effects with particular care: retries and repeated events are normal parts of controller operation.
  4. Report useful status when appropriate. JOSDK’s UpdateControl is the mechanism for managing updates to the custom resource, commonly its status. Keep status informative about observed progress or conditions, and do not use it to obscure whether the desired state was achieved.

A useful design test is to ask what happens if the same resource is reconciled again immediately after success, or if the process stops after making a change but before recording status. The next run should be able to inspect the API and continue without creating duplicate effects.

Test decisions and API interactions

Separate tests of desired-state decisions from tests of Kubernetes API interactions. Unit-level tests can verify that given a resource specification and observed state, the controller chooses the appropriate action. For client interaction tests, Fabric8 documents a mock server that can return expected API responses; JOSDK also advertises framework-level testing support.

  • Test that an absent dependent object is created and an already-correct one is not needlessly recreated.
  • Test that differences between desired and observed state lead to an appropriate update.
  • Test retry-sensitive paths and status reporting, including failure responses that the controller should handle.
  • Use a real-cluster integration check for behavior that a mock cannot establish, such as actual API-server validation, permissions, or the interaction of deployed components.

A mock server is a way to exercise client behavior against configured responses; it is not a complete Kubernetes API server. A passing mock test alone cannot prove that a CRD installs correctly, that RBAC is sufficient, or that the controller behaves correctly in a target cluster.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Configure access for where the controller runs

During development, a Java client can use kubeconfig to connect to a cluster. When deployed in Kubernetes, a controller can instead use its service account configuration. The Kubernetes Java-client guidance discusses kubeconfig, while the Fabric8 documentation describes kubeconfig and service-account configuration options.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Access is not one-size-fits-all. Derive RBAC from the resources the controller actually watches and changes, and grant only the verbs those operations require. A controller that watches a custom resource and manages Deployments and ConfigMaps needs permissions based on those API interactions; the exact rules depend on the implementation and target cluster.

Package and deploy the controller

For a cluster deployment, package the controller as a containerized workload and deploy it, commonly as a Kubernetes Deployment. Include the CRD manifest if the controller relies on a custom resource, and ensure it is installed as part of the release workflow before users create instances. The workload also needs appropriately scoped access to watch its inputs and manage its dependent resources.

Before deploying beyond a learning cluster, verify the selected Java, JOSDK, and client versions against their current release documentation, inspect the generated or authored CRD, and validate the RBAC rules against the controller’s actual API calls. The cited sources do not establish one universal version set or RBAC manifest: both depend on the releases and behavior you choose.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.