Skip to main content
Version: v1.4.0-m.1 (pre-release)

Deploy and Explore

This guide walks you through deploying a component on OpenChoreo and exploring what the platform creates behind the scenes. By the end, you'll understand the full resource chain, from the Component you define to the Kubernetes Deployment running your code.

This guide contains steps to deploy an OpenChoreo sample service or to deploy from your own codebase.

Already deployed via Quick Start?

If you followed the Quick Start Guide, you've already deployed a sample app. This page revisits the process step by step so you can understand what each resource does.

Prerequisites​

  • OpenChoreo installed on your cluster (see Local Setup or Your Own Cluster)
  • occ CLI installed and configured for your OpenChoreo installation
  • kubectl configured and pointing at your cluster (for the Kubernetes-level steps in this guide)

Deploy the Sample​

We'll deploy the Go Greeter Service from a pre-built container image. The sample YAML contains two key resources:

  • Component: declares the application, referencing the deployment/service ClusterComponentType
  • Workload: specifies the container image, ports, environment variables, and an external endpoint
kubectl apply -f https://raw.githubusercontent.com/openchoreo/openchoreo/release-v1.4.0-m.1/samples/from-image/go-greeter-service/greeter-service.yaml

Wait for the deployment to be ready:

kubectl wait --for=condition=Ready component/greeter-service -n default --timeout=120s

Skip ahead to Explore What OpenChoreo Created, or read on to deploy your own code instead.

Deploy Your Own Codebase​

If you already have your own codebase, you can follow the steps below to deploy it in OpenChoreo. There are two routes to follow.

  1. If you only have the source code, you can build and deploy it by following Route A.
  2. If you already have a container image, you can deploy it by following Route B.

Whichever route you take, OpenChoreo needs two things:

  • a Component, declaring which ComponentType to deploy with and where your code or image lives
  • a Workload, declaring how your container runs: image, endpoints, environment variables, files, and dependencies

The way the Workload gets created differs based on the route you take.

Where your image comes fromWhat you authorHow the Workload is created
OpenChoreo builds your source codeA Component with spec.workflow, plus a workload.yaml file in your repositoryThe build generates it
You already have a container imageA Component and a Workload resourceYou write it

Route A: Build from Source​

Prerequisites​

  • A Workflow Plane, which the quick start does not install by default. Add --with-build to the installer, then confirm it is there:

    occ clusterworkflowplane list
    occ clusterworkflow list

    The second command lists the build workflows you can reference, such as dockerfile-builder and paketo-buildpacks-builder.

  • A public Git repository containing your application. For private repositories, see Private Repository Access.

1. Describe your runtime​

Commit a workload Descriptor at the root of your application directory (the path you will set as repository.appPath) to declare what your service exposes:

apiVersion: openchoreo.dev/v1alpha1

metadata:
name: my-service-workload

endpoints:
- name: http
type: HTTP
port: 8080
visibility:
- external

configurations:
env:
- name: LOG_LEVEL
value: info

Set port to the port your application actually listens on, and keep external only if you want the endpoint reachable through the public gateway. Environment variables, mounted files, and dependencies on other components or on databases all go in this file. Refer Workload Descriptor for more details.

2. Create the Component​

The Component points at your repository and names the build workflow to run:

# my-service.yaml
apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-service
namespace: default
spec:
owner:
projectName: default
componentType:
kind: ClusterComponentType
name: deployment/service
autoDeploy: true
workflow:
kind: ClusterWorkflow
name: dockerfile-builder
parameters:
repository:
url: "https://github.com/my-org/my-service"
revision:
branch: "main"
appPath: "/"
docker:
context: "."
filePath: "./Dockerfile"
occ apply -f my-service.yaml

autoDeploy: true deploys the result as soon as a build succeeds in the next step.

3. Trigger a build​

occ component workflow run my-service

If you haven't installed the CLI, create the WorkflowRun yourself. The two labels are what link the build to your Component, and the workflow must match the one on the Component:

# my-service-build-01.yaml
apiVersion: openchoreo.dev/v1alpha1
kind: WorkflowRun
metadata:
name: my-service-build-01
namespace: default
labels:
openchoreo.dev/project: "default"
openchoreo.dev/component: "my-service"
spec:
workflow:
kind: ClusterWorkflow
name: dockerfile-builder
parameters:
repository:
url: "https://github.com/my-org/my-service"
revision:
branch: "main"
appPath: "/"
docker:
context: "."
filePath: "./Dockerfile"

Save it to a file and create it:

kubectl apply -f my-service-build-01.yaml

Follow the build. occ component workflow run generates the WorkflowRun name and prints it, so substitute that name here:

occ workflowrun get <workflowrun-name> -n default
occ workflowrun logs <workflowrun-name> -f

If you created the WorkflowRun yourself, the name is the one you set in the manifest above. Either way, you can list the runs for your component by label:

kubectl get workflowrun -n default -l openchoreo.dev/component=my-service

occ workflowrun logs requires the CLI. Without it, follow progress through status.tasks on the run:

kubectl get workflowrun <workflowrun-name> -n default -o yaml

The run moves through checkout-source, the build step, publish-image, and finally generate-workload-cr — the step that turns your descriptor into a Workload.

4. Check the Workload the build produced​

occ workload list -n default

Confirm the image and endpoints are what you expected:

occ workload get my-service-workload -n default

Since we set autoDeploy: true earlier, the Workload should now be deploying. Continue at Explore What OpenChoreo Created.

Route B: Deploy an Image You Already Built​

If your own CI already publishes images, skip the workflow entirely and write the Workload yourself:

apiVersion: openchoreo.dev/v1alpha1
kind: Component
metadata:
name: my-service
namespace: default
spec:
owner:
projectName: default
componentType:
kind: ClusterComponentType
name: deployment/service
autoDeploy: true
---
apiVersion: openchoreo.dev/v1alpha1
kind: Workload
metadata:
name: my-service-workload
namespace: default
spec:
owner:
projectName: default
componentName: my-service
container:
image: ghcr.io/my-org/my-service:v1.0.0
env:
- key: LOG_LEVEL
value: info
endpoints:
http:
type: HTTP
port: 8080
visibility:
- external

Apply both resources together:

occ apply -f my-service.yaml
kubectl wait --for=condition=Ready component/my-service -n default --timeout=120s

Continue at Explore What OpenChoreo Created.

Explore What OpenChoreo Created​

When you followed the steps above, OpenChoreo's controllers reconciled your Component and Workload into the same chain of resources. Let's walk through each one.

The commands in this section take the component name from a shell variable. Run only the line that matches the component you just deployed:

# The sample from "Deploy the Sample"
export COMPONENT=greeter-service

# Or your own, from "Deploy Your Own Codebase"
# export COMPONENT=my-service

The Resource Chain​

1. Component​

The Component declares your application and links it to a platform-defined template (ClusterComponentType). With autoDeploy: true, OpenChoreo automatically creates a release and deploys it to the first environment in the deployment pipeline. Later environments in the pipeline are not deployed automatically; each one requires a promotion.

occ component get $COMPONENT -n default

Look at status.latestRelease.name in the output to see which ComponentRelease was created:

status:
latestRelease:
name: greeter-service-5d7f658d9c

The suffix is a hash derived from the release spec, so your value will differ.

2. ComponentRelease​

The ComponentRelease is an immutable snapshot that freezes the Component's configuration, including the ComponentType spec, Trait definitions, parameters, and Workload. This enables reliable rollbacks and audit trails.

occ componentrelease list --project default --component $COMPONENT -n default

The name includes a hash of the spec, so a new release is only created when something actually changes.

3. ReleaseBinding​

The ReleaseBinding binds a ComponentRelease to a specific environment. It references the release name and the target environment (development). This is where environment-specific overrides (like replica counts or resource limits) can be applied.

occ releasebinding list --project default --component $COMPONENT -n default

The name follows the convention {component}-{environment}.

4. Underlying Kubernetes Resources​

From the ReleaseBinding, OpenChoreo renders the final Kubernetes manifests and applies them to a data plane namespace:

  • Deployment: manages the pod running your container image
  • Service: provides stable networking for the pod
  • HTTPRoute: configures the API gateway to route external traffic to your service, created for each endpoint with external visibility
kubectl get deployment,svc,httproute -A -l openchoreo.dev/component=$COMPONENT

Notice these resources live in a data plane namespace (e.g., dp-default-default-development-*), not in the default namespace where you created your Component. This separation is by design: the control plane manages intent while the data plane runs workloads.

Test the Running Service​

External endpoints are routed at /{component}-{endpoint}, so an endpoint named http is reachable at /$COMPONENT-http:

curl http://development-default.openchoreoapis.localhost:19080/$COMPONENT-http/

The sample's greeter serves /greeter/greet under that prefix:

curl http://development-default.openchoreoapis.localhost:19080/greeter-service-http/greeter/greet
Hello, Stranger!

Try it with a name parameter:

curl "http://development-default.openchoreoapis.localhost:19080/greeter-service-http/greeter/greet?name=OpenChoreo"
Hello, OpenChoreo!

The URL structure is: http://{environment}-{namespace}.{gateway-host}/{component}-{endpoint}/{path}

Summary​

However you supplied the Component and Workload, a sample, a build from your source, or an image you already had, OpenChoreo created the same deployment chain:

Component → ComponentRelease (immutable snapshot) → ReleaseBinding (binds to environment) → Deployment + Service + HTTPRoute (running on data plane)

To learn more about these abstractions, see Resource Relationships and Runtime Model.

Clean Up​

To remove the sample:

kubectl delete -f https://raw.githubusercontent.com/openchoreo/openchoreo/release-v1.4.0-m.1/samples/from-image/go-greeter-service/greeter-service.yaml

To remove your own component, delete the Component and workload. The ComponentRelease, ReleaseBinding, and the data plane resources are garbage collected with it:

occ component delete $COMPONENT -n default
occ workload delete $COMPONENT-workload -n default