Skip to main content

Workloads and Endpoints

The Workload is the runtime contract of a Component: what container to run, what it exposes to the network, and what it depends on. Every Component has exactly one Workload. You either author it directly (for a prebuilt image) or let a build generate it from your source plus an optional workload.yaml descriptor.

note

DevsPortal is built on the Control Plane Operator engine. The openchoreo.dev/v1alpha1 Workload resource and occ CLI below are unchanged engine internals.

Portal first, CLI second

The portal UI is the recommended path; the equivalent occ CLI commands follow for scripting.

Defining a Workload in the portal

You rarely write the Workload YAML by hand for a new component. The Create Component wizard captures the same contract through a form:

  • Build & Deploy — choose where the image comes from (Container Image for a prebuilt image, or Build from Source to have the platform build it) and, for a prebuilt image, enter the image reference, command/args, environment variables, and mounted files.
  • Service Details — add the network endpoints the component exposes: for each one pick a type (HTTP, gRPC, …), a port, an optional base path, and a visibility level.

When you click Create, the portal writes exactly the Workload described below. To change the contract later, open the component and edit its workload from the relevant tab. The rest of this page documents every field that form maps to — useful whether you fill the form or author the YAML directly for scripting.

Anatomy of a Workload

A Workload has three meaningful sections under spec: an owner that ties it to its Component, a container that says what to run, and endpoints (plus dependencies) that say how it connects.

apiVersion: openchoreo.dev/v1alpha1
kind: Workload
metadata:
name: cart-api
namespace: fedshi
spec:
owner:
projectName: checkout
componentName: cart-api
container:
# what to run
endpoints:
# what it exposes
dependencies:
# what it needs — see the Dependencies page

The owner field links the Workload to its Project and Component and is immutable after creation. From DevsPortal's side, the Workload is the single source of truth that gets rendered into a Deployment, a Service, HTTPRoutes, and NetworkPolicies on the data plane.

The container

Only image is required. The rest let you shape the runtime.

FieldRequiredDescription
imageYesOCI image to run (tag or digest)
commandNoContainer entrypoint
argsNoArguments for the entrypoint
envNoEnvironment variables
filesNoFiles mounted into the container

A Fedshi service pulling from the internal Harbor registry:

container:
image: registry.idp.fedshi.com/checkout/cart-api:1.4.0
args: ["--port", "8080"]

Environment variables

Set literal values, or pull from a Secret:

container:
image: registry.idp.fedshi.com/checkout/cart-api:1.4.0
env:
- key: LOG_LEVEL
value: info
- key: DB_PASSWORD
valueFrom:
secretKeyRef:
name: cart-db-secrets
key: password

Each entry sets exactly one of value or valueFrom. For values that vary by stage (a different log level in prod than dev), don't hardcode them here — use environment overrides instead, so the same release behaves differently per environment.

Files

Mount config files from literal content or a Secret:

container:
image: registry.idp.fedshi.com/checkout/cart-api:1.4.0
files:
- key: config.yaml
mountPath: /etc/config
value: |
server:
port: 8080
- key: tls.crt
mountPath: /etc/tls
valueFrom:
secretKeyRef:
name: cart-tls
key: certificate

Each file needs a key and a mountPath, and exactly one of value or valueFrom.

Endpoints

Endpoints are the network interfaces your component exposes. They're a map keyed by endpoint name:

endpoints:
http:
type: HTTP
port: 8080
visibility: [external]
basePath: /api/v1
grpc:
type: gRPC
port: 9090
visibility: [namespace]
FieldRequiredDescription
typeYesHTTP, gRPC, GraphQL, Websocket, TCP, or UDP
portYesPort the endpoint exposes (1–65535)
targetPortNoContainer port to forward to (defaults to port)
visibilityNoAdditional visibility scopes beyond the implicit project
basePathNoBase path of the API the endpoint serves
displayNameNoHuman-readable name shown in the portal
schemaNoAPI schema (e.g. an OpenAPI spec) surfaced in the catalog

Endpoint visibility

Visibility is the single most important decision per endpoint: it controls both who can route to the endpoint and what the network policy allows. Every endpoint always gets project visibility implicitly; the visibility array widens it.

VisibilityReachable fromWhen to use
projectOther components in the same project + environment (implicit)Internal service-to-service calls within one project
namespaceAny project in the same namespace + environmentA shared service other teams in your namespace consume
internalAny namespace across the deploymentA platform-wide internal service
externalThe public internet, with TLSPublic APIs and user-facing web apps

Concretely, on Fedshi:

  • A cart-api that only the checkout web app calls → project (the default — leave the array empty).
  • A shared-auth service other teams call → add namespace.
  • The customer-facing storefront → add external.

An external endpoint gets a public HTTPRoute on the external gateway and a NetworkPolicy that admits ingress from outside the cluster. Its public host follows the pattern {component}-{environment}-{project}.apps.idp.fedshi.com on the {fedshi.apps} wildcard. For example, the storefront in production:

curl https://storefront-production-storefront.apps.idp.fedshi.com/
Default to the narrowest visibility

Only mark an endpoint external if it genuinely needs to be on the public internet. Most backend services should stay project or namespace. Over-exposing an endpoint widens both its route and its network policy. When in doubt, start narrow — you can always widen later.

A complete Workload

A Fedshi backend service with one external HTTP endpoint:

apiVersion: openchoreo.dev/v1alpha1
kind: Workload
metadata:
name: cart-api
namespace: fedshi
spec:
owner:
projectName: checkout
componentName: cart-api
container:
image: registry.idp.fedshi.com/checkout/cart-api:1.4.0
args: ["--port", "8080"]
env:
- key: LOG_LEVEL
value: info
endpoints:
http:
type: HTTP
port: 8080
basePath: /api/v1
visibility: [external]

In the portal, this is what the Build & Deploy and Service Details wizard steps produce — one external HTTP endpoint on port 8080 with LOG_LEVEL=info.

Or with the occ CLI, apply it, then inspect it:

occ apply -f cart-api-workload.yaml
occ workload get cart-api -n fedshi
occ workload list -n fedshi

Authoring directly vs from a build

How you produce the Workload depends on your deployment pattern:

  • Prebuilt image — you write the Workload by hand (as above) and apply it. You own the image field.
  • Build from source — the build sets the image for you. To get endpoints, env vars, files, and dependencies into the generated Workload, add a workload.yaml descriptor to your repository. Its shape mirrors what you've seen here; see Builds and CI → the workload descriptor.

What's next

  • Dependencies — consume another component's endpoint or a managed resource, and let the platform inject the connection details.
  • Deploy and promote — ship the workload across environments with per-environment overrides.
  • Builds and CI — generate the workload from your source.