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.
DevsPortal is built on the Control Plane Operator engine. The
openchoreo.dev/v1alpha1 Workload resource and occ CLI below are unchanged engine
internals.
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.
| Field | Required | Description |
|---|---|---|
image | Yes | OCI image to run (tag or digest) |
command | No | Container entrypoint |
args | No | Arguments for the entrypoint |
env | No | Environment variables |
files | No | Files 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]
| Field | Required | Description |
|---|---|---|
type | Yes | HTTP, gRPC, GraphQL, Websocket, TCP, or UDP |
port | Yes | Port the endpoint exposes (1–65535) |
targetPort | No | Container port to forward to (defaults to port) |
visibility | No | Additional visibility scopes beyond the implicit project |
basePath | No | Base path of the API the endpoint serves |
displayName | No | Human-readable name shown in the portal |
schema | No | API 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.
| Visibility | Reachable from | When to use |
|---|---|---|
project | Other components in the same project + environment (implicit) | Internal service-to-service calls within one project |
namespace | Any project in the same namespace + environment | A shared service other teams in your namespace consume |
internal | Any namespace across the deployment | A platform-wide internal service |
external | The public internet, with TLS | Public APIs and user-facing web apps |
Concretely, on Fedshi:
- A
cart-apithat only the checkout web app calls →project(the default — leave the array empty). - A
shared-authservice other teams call → addnamespace. - The customer-facing
storefront→ addexternal.
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/
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
imagefield. - Build from source — the build sets the
imagefor you. To get endpoints, env vars, files, and dependencies into the generated Workload, add aworkload.yamldescriptor 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.