Applies to VAST Cluster 5.5.
A pipeline is defined by one file: the file that vastde pipelines create --config and vastde pipelines update --config take. It names the pipeline, says which compute cluster and namespace it runs in, and holds the manifest: the triggers, the function deployments, and the links that connect them. Keep this file in Git. It's the source of truth for the pipeline.
This page lists every field in the file, what the server fills in, what you can't change after creation, what a deploy needs, and how updates and revisions behave. For a walkthrough, see pipelines as code. For the trigger and function files, see function and trigger files.
The file at a glance
name: media-pipeline # required
description: Thumbnails and index entries for new images
tags: [media, dev]
kubernetes_cluster_vrn: vast:dataengine:kubernetes-clusters:compute-1 # required
namespace: dataengine-ns-<tenant-guid> # required: your tenant's DataEngine namespace
manifest:
config: # applies to every function deployment
environment_variables: []
secrets: []
triggers: [] # triggers this pipeline listens to
function_deployments: [] # functions this pipeline runs, and how
links: [] # who invokes whom
The file is YAML or JSON. Keys are the API's field names, in snake_case, except the two keys of a conditional trigger label (triggerLabelName, triggerLabelValue). --config takes a file path, a path prefixed with @, or inline JSON (a value starting with { or [).
A complete example is at the end of the page.
Top-level fields
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | Yes | The pipeline's name. Lowercase letters, digits and hyphens. You can't change it after creation. |
description |
string | No | Printable ASCII. On pipelines update, leaving it out clears the stored description, so keep it in the file. |
tags |
list of strings | No | Up to 32 tags. Each tag may contain only lowercase letters, digits and hyphens. |
kubernetes_cluster_vrn |
VRN | Yes | The compute cluster the pipeline runs on: vast:dataengine:kubernetes-clusters:<cluster-name>. vastde compute-clusters list shows the clusters linked to your tenant. The CLI doesn't turn a cluster name into a VRN for you. You can't change it after creation. |
namespace |
string | Yes | The Kubernetes namespace the pipeline's functions run in: your tenant's DataEngine namespace on that cluster, dataengine-ns-<tenant GUID>. It's created when the platform team attaches your tenant to the cluster. vastde compute-clusters get <cluster> -o yaml lists it under namespaces. It must be one of your tenant's namespaces on that cluster. You can't change it after creation. |
manifest |
object | No | The pipeline's contents. A pipeline can be created with no manifest, but it can't be deployed until the manifest meets the deploy requirements. |
The API documents kubernetes_cluster_vrn and namespace as optional; the server requires both on create.
On pipelines create, the --name, --description and --tags flags override the values in the file.
manifest.config
Settings for every function deployment in the pipeline.
| Field | Type | Notes |
|---|---|---|
environment_variables |
list of {name, value} |
Both name and value are non-empty strings. A function deployment's own variable with the same name overrides the pipeline's. |
secrets |
list of strings | Names of Kubernetes Secrets in the pipeline's namespace. Every function deployment gets them. |
Environment variable names that start with VAST_, VASTPIPELINE_ or K_, and a few other names the runtime uses (HOSTNAME, PORT, PERFORMANCE), are rejected. VAST_FUNC_HANDLER is allowed.
Secrets:
- A secret is checked for existence only when you deploy, not when you create or update the pipeline.
- The same secret name can't be listed both here and in a function deployment's
config.secrets. The server rejects the manifest. - You create secrets with
vastde pipelines create|update --secret-file <file>(repeatable). The file holdsname,kubernetes_cluster_vrn,namespaceandentries: [{key, value}]. The CLI creates or replaces the secret before it sends the pipeline, but it doesn't add the secret's name to the manifest: list it insecretsyourself. The CLI warns about a name in the manifest that it didn't create. Don't commit a secret file to Git. See security.
manifest.triggers
The triggers this pipeline listens to. A trigger is a separate object that you create first (see function and trigger files); the manifest refers to it.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | Yes | A local name, used only inside this manifest to refer to the trigger in links. It can be the trigger's own name. |
vrn |
VRN | Yes | The trigger: vast:dataengine:triggers:<trigger-name>. It must exist when you create or update the pipeline. |
triggers:
- name: uploads
vrn: vast:dataengine:triggers:uploads-created
manifest.function_deployments
One entry per function the pipeline runs. A function deployment is a function plus the settings it runs with in this pipeline. The same function can appear twice under different names.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | Yes | A local name, at most 40 characters, used in links. It's also part of the name of the Kubernetes service that runs the function. |
function_vrn |
VRN | Yes | The function: vast:dataengine:functions:<function-name>. It must exist when you create or update the pipeline. |
revision |
integer or null | No | The function revision to run. See Pinning a revision. |
config |
object | No | Environment, secrets, log level and batching. See config. |
resources |
object | No | Replicas, CPU, memory, timeout, workers and autoscaling. See resources. |
Pinning a revision
revision: <n>runs revision n of the function on every deploy.revisionomitted ornullruns the function's default revision. If the function has no default revision set, it runs the function's latest revision. The API documents this fordefault_revision_number.
An unpinned deployment is resolved when you deploy, not when you save the pipeline. Every deploy picks up whatever the function's default or latest revision is at that moment. Creating a function revision doesn't change a running pipeline until the next deploy.
Pin the revision in Git for anything you promote between environments, so that a deploy runs exactly what the file says. For how revisions are created, see function and trigger files.
function_deployments[].config
| Field | Type | Notes |
|---|---|---|
environment_variables |
list of {name, value} |
As in manifest.config. These override pipeline-level variables with the same name. |
secrets |
list of strings | Kubernetes Secret names for this deployment only. |
log_level |
string | NOTSET, DEBUG, INFO, WARNING, ERROR or CRITICAL. The VAST Web UI's default is INFO. |
event_batching |
object | Deliver events to the function in batches. See below. |
event_batching:
| Field | Type | Range | Notes |
|---|---|---|---|
batch_max_size |
integer | 1–512 | The most events in one batch. |
batch_timeout_ms |
integer | 0–60000 | How long to wait, in milliseconds, before invoking the function with a partial batch. |
- If you set
event_batching, set both fields. The API requires them. - With
batch_max_sizeabove 1,batch_timeout_msmust be above 0. Withbatch_max_size: 1, it must be 0. Any other combination is rejected. - The function's handler must be written to take a batch. Turning batching on without a batch handler is liable to cause runtime failures. See write a function.
- Set the deployment's
resources.timeouthigher than the batch timeout. Duplicated batch-trace entries are a known issue in 5.5 when the two are combined badly.
function_deployments[].resources
| Field | Type | Default | Notes |
|---|---|---|---|
min_concurrency |
integer | 1 | The fewest instances (pods) of the function. |
max_concurrency |
integer | 10 | The most instances (pods). |
min_cpu |
string | 100m |
CPU guaranteed to each instance, as a Kubernetes quantity. |
max_cpu |
string | 500m |
CPU limit for each instance. |
min_memory |
string | 128Mi |
Memory guaranteed to each instance. |
max_memory |
string | 256Mi |
Memory limit for each instance. |
storage |
string | Not set | Ephemeral disk for each instance, for example 512Mi. |
timeout |
integer | Not stated | The function's timeout, in seconds. |
num_workers |
integer | 20 | Worker threads in each instance, 1–100. With batching, an instance handles up to num_workers × batch_max_size events at once, because each worker takes one batch. |
max_concurrent_requests_limit |
integer | Computed | The most requests one instance handles at once. If you leave it out, it's computed at deploy time as max(num_workers, batch_max_size). 0 means unlimited, which stops the autoscaler from seeing queue pressure. Set it only if you know your function's capacity. |
autoscaling |
object | See below | How the deployment scales between min_concurrency and max_concurrency. |
autoscaling_rps_factor |
integer | Deprecated and ignored. Don't use it. | |
autoscaling_concurrency_overload_factor |
string | Deprecated. Use autoscaling. |
There's no field for GPUs in 5.5.
The server rejects a deployment where:
autoscalingis set together with either deprecated field.max_concurrent_requests_limitis set (and not 0) but is lower than the concurrency autoscalingtarget, or lower thannum_workers × batch_max_sizewhen batching is on.
resources.autoscaling
metric is required. Provide the one configuration object that matches it.
| Field | Type | Notes |
|---|---|---|
metric |
string | concurrency (the default), rps or resource. |
concurrency |
object | Scale on in-flight requests per instance. Required when metric: concurrency. Supports scale to zero. |
rps |
object | Scale on requests per second per instance. Required when metric: rps. Supports scale to zero. |
resource |
object | Scale on CPU or memory use. Required when metric: resource. Doesn't support scale to zero. |
concurrency and rps take the same fields; concurrency adds hard_limit.
| Field | Type | Default | Range | Notes |
|---|---|---|---|---|
target |
integer | 20 | 1 or more | The level the autoscaler aims for per instance: in-flight requests for concurrency, requests per second for rps. |
target_utilization_percentage |
integer | 70 | 1–100 | Scale up when the average reaches this percentage of target. With target: 10 and 70, a new instance starts at an average of 7. |
stable_window_seconds |
integer | 60 | 6–3600 | The averaging window. With scale to zero, the last instance goes only after no traffic for this long. |
burst_window_percentage |
integer | 10 | 1–100 | The shorter window, as a percentage of the stable window, used to detect bursts. |
burst_threshold_percentage |
integer | 200 | 110–1000 | Burst mode starts when traffic exceeds this percentage of current capacity. |
scale_down_delay_seconds |
integer | 300 | 0 or more | How long to wait after load drops before scaling down. |
scale_to_zero_delay_seconds |
integer | 600 | 0 or more | How long to keep the last instance after the autoscaler decides to scale to zero. |
hard_limit |
integer | 0 | 0 or more | concurrency only. A hard cap on in-flight requests per instance; the rest wait. 0 is unlimited. The API warns it can hurt throughput and latency. |
resource:
| Field | Type | Required | Notes |
|---|---|---|---|
resource_autoscaling_type |
string | Yes | cpu or memory. |
target |
integer | Yes | For cpu, a percentage of the CPU request (80 means 80%). For memory, mebibytes (200 means 200Mi). |
stable_window_seconds |
integer | No | 6–3600. The scale-down stabilization window. If not set, the Kubernetes default applies. |
If a deployment has no autoscaling (and neither deprecated field), the server adds a concurrency block with target set to num_workers × batch_max_size before it stores the manifest. A deployment with no resources at all gets a complete block with the defaults above. You'll see them when you read the manifest back.
manifest.links
Links say who invokes whom. Each link connects one or more sources to one or more destinations. The API's rule: each source in source invokes every function deployment in destination, if all of the link's conditional trigger labels match.
| Field | Type | Required | Notes |
|---|---|---|---|
source |
list of strings | Yes | Local names from triggers or function_deployments. |
destination |
list of strings | Yes | Local names from function_deployments. |
topic |
VRN | No | The topic that carries events along this link. See Topics on links. |
config |
object | No | retries and events_order. |
conditional_trigger_labels |
list | No | Route only events that carry these labels. See Conditional routing. |
- Every name in
sourceanddestinationmust be defined intriggersorfunction_deployments. - You can't connect a trigger to a trigger, and you can't make a loop.
Topics on links
| Link | topic |
|---|---|
| Trigger → function | The link uses the trigger's own topic, the one the trigger publishes to. Leave topic out, or set it to that same topic; a different topic is rejected with Topic mismatch between trigger … and link. |
| Function → function | Leave topic out to use your tenant's default topic, or set a topic VRN. All links out of the same function must use the same topic. |
- A topic VRN is
vast:dataengine:topics:<broker>/<topic>, where<broker>is the broker name a trigger uses (broker.name; for a VAST Event Broker, the bucket name of the broker's view). - The dead-letter topic can't be used on a link.
- For topics themselves (partitions, retention), see topics in the VAST Event Broker section.
links[].config
| Field | Type | Values | Notes |
|---|---|---|---|
retries |
integer | How many times to retry delivering an event to the destination when the function fails or times out, after the first attempt: with retries: 2, the handler runs up to three times. After the last failed attempt, the event goes to the dead-letter topic. |
|
events_order |
string | ordered, unordered |
ordered processes one event per topic partition at a time, so concurrency is capped at the topic's partition count. unordered lets events be processed concurrently. |
The API gives no defaults for these. If you leave retries out, a server default applies, and a failing event can be retried for a long time before it reaches the dead-letter topic. Set retries on every link. See retries and the dead-letter topic.
The VAST Web UI shows Retries and Method of Delivery on the function deployment. In the file they belong to the link. See coming from the Web UI.
Conditional routing
conditional_trigger_labels makes a function-to-function link fire only for events that carry all of the listed labels with the listed values. The source function sets the labels on the events it returns; see the Runtime SDK reference.
| Field | Type | Pattern |
|---|---|---|
triggerLabelName |
string | ^[a-z][a-z0-9]{0,14}$: a lowercase letter, then up to 14 lowercase letters or digits. |
triggerLabelValue |
string | ^[a-zA-Z0-9]{1,64}$: 1 to 64 letters or digits. |
- Labels are ANDed: an event must match every label on the link.
- Only links whose sources are function deployments can have labels. A link from a trigger with labels is rejected.
- Label names must be unique within a link.
- Underscores aren't allowed in names or values.
links:
- source: [thumbnailer]
destination: [indexer]
conditional_trigger_labels:
- triggerLabelName: kind
triggerLabelValue: photo
What the server fills in
You don't write these fields. vastde pipelines get <name> -o yaml shows them.
| Field | Meaning |
|---|---|
id, guid |
The pipeline's identifiers. Most vastde commands accept the name or the GUID. |
vrn |
vast:dataengine:pipelines:<name> |
owner, tenant_guid |
Who created it, and the tenant. |
created_at, updated_at |
Timestamps. |
status |
Draft after create, InProgress during deploy, then Ready or Error; Deleting while being deleted. |
reason |
Free text explaining status, for example the Kubernetes condition that failed. |
last_revision_number |
The newest revision of the manifest. |
In the stored manifest, the server also:
- Fills in
resources, with the defaults and anautoscalingblock, where they're missing (see above).
When you read the manifest back, unpinned function deployments show revision: null, and an empty config section isn't shown.
At deploy time, without changing the stored manifest, it:
- Resolves each unpinned
revisionto the function's default or latest revision. - Computes
max_concurrent_requests_limitwhere it's not set.
Fields you can't change
| Field | What happens if you change it |
|---|---|
name |
vastde pipelines update refuses (cannot change pipeline name from '…' to '…'), and so does the server (Cannot change pipeline name). |
kubernetes_cluster_vrn |
Rejected. It's also required on every update, and must equal the stored value. |
namespace |
Rejected (Cannot change pipeline namespace). |
To move a pipeline to another cluster or namespace, create a new pipeline from the same file with a new name.
What a deploy requires
vastde pipelines deploy <name|GUID> takes no file. It deploys the pipeline's latest revision. vastde pipelines create --config <file> --deploy creates and deploys in one step.
A deploy fails unless:
manifest.triggershas at least one trigger.manifest.linkshas at least one link, and at least one link has a trigger as a source.- Every secret the manifest names exists in the namespace.
- Every function's container registry is linked to the pipeline's compute cluster and namespace. Otherwise the deploy fails with
Access to Container registry … is denied for the kubernetes cluster …. That's a platform-team fix; see setup prerequisites.
Create and update check the rest when you submit the file: that the cluster VRN is there and the namespace belongs to that cluster, that the triggers and functions exist, that link names resolve, that no environment variable has a reserved name, that no secret is named at both levels, and the batching, autoscaling, topic and label rules on this page.
A failed deploy check doesn't undo the create: vastde pipelines create --config <file> --deploy that fails at the deploy step leaves the pipeline in Draft. Fix the file, then run vastde pipelines update and vastde pipelines deploy, or delete the pipeline. The messages for each check are in the error reference.
Updates and revisions
vastde pipelines update <name|GUID> --config <file> replaces the pipeline's definition with the file. Each manifest is stored as a revision.
Send whole sections. The four manifest sections (config, triggers, function_deployments, links) are each replaced as a whole when they're in the file. A section you leave out is kept from the latest revision; inside config, the same applies to secrets and environment_variables separately.
The top-level description isn't kept. Unlike a manifest section, a description you leave out of the file is cleared on update, not kept.
- To remove everything in a section, send an empty list (
links: []). Leaving it out doesn't remove it. - To remove one link or one function deployment, send the section without it.
- Always include
manifest, and keep the file complete. A complete file in Git gives the same result whatever the cluster holds.
Revisions.
| Latest revision | What update does |
|---|---|
| Deployed | Adds a new revision with the next number. The running pipeline doesn't change. |
| Not deployed | Overwrites the latest revision in place. No new number. |
pipelines createmakes revision 1.- Updating doesn't redeploy. Run
vastde pipelines deployto put the new revision live. - An update adds a revision even when the file is identical to the latest one, if that one is deployed.
- Deploy always takes the latest revision. There's no command to deploy an older revision. To roll back, check out the earlier file from Git, run
update, and deploy. vastde pipelines get <name> --manifestshows the latest revision's manifest; add--deployedto see the deployed one.
No version check. Updates carry no version or ETag, so the last writer wins, section by section. An edit saved in the VAST Web UI and an update from an old copy of the file overwrite each other without a warning. Pick one place to edit each pipeline. For pipelines you manage from Git, treat the Web UI as read-only. See coming from the Web UI.
Complete example
One element trigger, uploads-created, watches the media-uploads bucket. Its events go to thumbnailer, which passes events on to indexer. indexer takes events in batches. The trigger and the two functions must exist before you create the pipeline; their files are in function and trigger files.
The example file as the graph it describes, with the section of the file that defines each part.
# media-pipeline.yaml
name: media-pipeline
description: Thumbnails and index entries for new images
tags: [media, dev]
kubernetes_cluster_vrn: vast:dataengine:kubernetes-clusters:compute-1
namespace: dataengine-ns-<tenant-guid> # your tenant's DataEngine namespace on compute-1
manifest:
config: # every function deployment gets these
environment_variables:
- name: OUTPUT_BUCKET
value: media-derived
secrets:
- media-s3-keys # Kubernetes Secret in the namespace; create it with --secret-file
triggers:
- name: uploads # local name, used in links below
vrn: vast:dataengine:triggers:uploads-created
function_deployments:
- name: thumbnailer # local name, at most 40 characters
function_vrn: vast:dataengine:functions:thumbnailer
revision: 3 # pinned; omit to follow the default or latest revision
config:
log_level: INFO
environment_variables:
- name: THUMBNAIL_WIDTH
value: "320" # values are strings
resources:
min_concurrency: 1
max_concurrency: 8
min_cpu: 250m
max_cpu: "1"
min_memory: 256Mi
max_memory: 512Mi
timeout: 120 # seconds
autoscaling:
metric: concurrency # scale on in-flight requests per instance
concurrency:
target: 20
target_utilization_percentage: 70
- name: indexer
function_vrn: vast:dataengine:functions:indexer
revision: 1
config:
log_level: INFO
event_batching: # the handler must accept a batch
batch_max_size: 50
batch_timeout_ms: 2000 # must be > 0 when batch_max_size > 1
resources:
min_concurrency: 1
max_concurrency: 4
num_workers: 4 # up to 4 x 50 events in flight per instance
timeout: 60 # longer than the batch timeout
# no autoscaling block: the server adds a concurrency default
links:
- source: [uploads] # trigger -> function: uses the trigger's topic
destination: [thumbnailer]
config:
retries: 3
events_order: unordered
- source: [thumbnailer] # function -> function: no topic, so the tenant default topic
destination: [indexer]
config:
retries: 3
events_order: unordered
Create it and deploy it:
vastde pipelines create --config media-pipeline.yaml --secret-file media-s3-keys.yaml --deploy
After you edit the file:
vastde pipelines update media-pipeline --config media-pipeline.yaml
vastde pipelines deploy media-pipeline
Exporting an existing pipeline
Use this to bring a pipeline that was built in the VAST Web UI, or by someone else, under Git.
From the CLI. vastde pipelines get <name> --manifest -o yaml prints the latest revision's manifest, and only the manifest: no name, kubernetes_cluster_vrn or namespace. It isn't a file pipelines update accepts as it stands. Wrap it:
- Run
vastde pipelines get <name> -o yamland copyname,kubernetes_cluster_vrnandnamespace(anddescriptionandtagsif you use them). Leave out the read-only fields (id,guid,vrn,status,reason,last_revision_number, timestamps, owner). - Put the output of
vastde pipelines get <name> --manifest -o yamlunder a top-levelmanifest:key, indented one level.
vastde pipelines get media-pipeline -o yaml
vastde pipelines get media-pipeline --manifest -o yaml
Add --deployed to the second command to export the deployed revision rather than the latest one. Without -o yaml, --manifest prints JSON.
From the Web UI. The Visual Builder's YAML view has a Download button that saves pipeline-manifest.yaml, with name, description, tags, namespace, kubernetes_cluster_vrn and manifest: the full file.
Either way, the exported manifest isn't exactly the file that created the pipeline. It includes the resources the server filled in, with their autoscaling blocks, and revision: null on unpinned deployments, and the CLI export leaves out an empty config. You can keep the filled-in values or delete them; the server adds them again where they're missing. Delete revision: null or replace it with a revision number to pin the deployment. The wrapped CLI export is accepted by pipelines update as it is: re-applying it unchanged left the exported manifest identical. Add description (and tags) to the wrapper if the pipeline has them, or the update clears them. Check the export into Git, run vastde pipelines update <name> --config <file> once to confirm it's accepted, and from then on change the pipeline only through the file.
See also
- Pipelines as code: the workflow end to end.
- Function and trigger files
- Coming from the Web UI
- CLI reference
- Runtime SDK reference: batch handlers and trigger labels.
- Building and Deploying a Pipeline on VAST DataEngine on the KB
- Create a new Pipeline in the VAST DataEngine API reference