Kubernetes · Arazzo Workflow

Kubernetes Run a One-Off Task Pod and Collect Its Output

Version 1.0.0

Create a run-to-completion pod, poll it until it finishes, read its log, then clean it up.

1 workflow 1 source API 1 provider
View Spec View on GitHub AutomationCloud NativeCNCFContainersDeploymentOpen SourceOrchestrationScalingArazzoWorkflows

Provider

kubernetes

Workflows

run-one-off-pod
Create a run-to-completion pod, read its output, and delete it.
Creates a pod that runs a command to completion, polls the pod until it reaches a terminal phase, reads the log as the task result, and removes the pod.
4 steps inputs: args, command, env, image, namespace, serviceAccountName, tailLines, taskName outputs: logOutput, phase, podName
1
createTaskPod
createNamespacedPod
Create the task pod with restartPolicy Never so a failed command is left in the Failed phase for inspection rather than being restarted forever.
2
pollTaskPod
getNamespacedPod
Read the pod until it leaves the Pending phase. Succeeded means the command exited zero; Failed means it exited non-zero.
3
collectTaskLog
readNamespacedPodLog
Read the container log as the task's output. This is the only place the command's stdout is retained once the pod is deleted.
4
cleanupTaskPod
deleteNamespacedPod
Delete the completed task pod so finished one-off runs do not accumulate. The log has already been collected by the previous step.

Source API Descriptions

Arazzo Workflow Specification

Raw ↑
arazzo: 1.0.1
info:
  title: Kubernetes Run a One-Off Task Pod and Collect Its Output
  summary: Create a run-to-completion pod, poll it until it finishes, read its log, then clean it up.
  description: >-
    The batch primitive behind migrations, backfills, and smoke tests. The
    workflow creates a pod with restartPolicy Never so it runs to completion,
    reads it back until the phase leaves Pending, collects the container log as
    the task's output, and deletes the pod so completed task pods do not
    accumulate in the namespace. Every step spells out its request inline so the
    flow can be read and executed without opening the underlying OpenAPI
    description.
  version: 1.0.0
sourceDescriptions:
- name: kubernetesApi
  url: ../openapi/kubernetes-api-openapi.yml
  type: openapi
workflows:
- workflowId: run-one-off-pod
  summary: Create a run-to-completion pod, read its output, and delete it.
  description: >-
    Creates a pod that runs a command to completion, polls the pod until it
    reaches a terminal phase, reads the log as the task result, and removes the
    pod.
  inputs:
    type: object
    required:
    - namespace
    - taskName
    - image
    properties:
      namespace:
        type: string
        description: The namespace to run the task pod in.
      taskName:
        type: string
        description: Name for the one-off pod and its container.
      image:
        type: string
        description: Container image that carries the task.
      command:
        type: array
        description: Entrypoint command array, replacing the image ENTRYPOINT.
        items:
          type: string
      args:
        type: array
        description: Arguments to the entrypoint, replacing the image CMD.
        items:
          type: string
      env:
        type: array
        description: Environment variables to set in the task container.
        items:
          type: object
      serviceAccountName:
        type: string
        description: Service account granting the task pod its API permissions.
      tailLines:
        type: integer
        description: Number of log lines to collect from the end of the log.
  steps:
  - stepId: createTaskPod
    description: >-
      Create the task pod with restartPolicy Never so a failed command is left
      in the Failed phase for inspection rather than being restarted forever.
    operationId: createNamespacedPod
    parameters:
    - name: namespace
      in: path
      value: $inputs.namespace
    requestBody:
      contentType: application/json
      payload:
        apiVersion: v1
        kind: Pod
        metadata:
          name: $inputs.taskName
          namespace: $inputs.namespace
          labels:
            app: $inputs.taskName
            role: one-off-task
        spec:
          restartPolicy: Never
          serviceAccountName: $inputs.serviceAccountName
          terminationGracePeriodSeconds: 30
          containers:
          - name: $inputs.taskName
            image: $inputs.image
            imagePullPolicy: IfNotPresent
            command: $inputs.command
            args: $inputs.args
            env: $inputs.env
            resources:
              requests:
                cpu: 100m
                memory: 128Mi
              limits:
                cpu: '1'
                memory: 1Gi
    successCriteria:
    - condition: $statusCode == 201
    outputs:
      podName: $response.body#/metadata/name
      podUid: $response.body#/metadata/uid
  - stepId: pollTaskPod
    description: >-
      Read the pod until it leaves the Pending phase. Succeeded means the
      command exited zero; Failed means it exited non-zero.
    operationId: getNamespacedPod
    parameters:
    - name: namespace
      in: path
      value: $inputs.namespace
    - name: name
      in: path
      value: $steps.createTaskPod.outputs.podName
    successCriteria:
    - condition: $statusCode == 200
    - context: $response.body
      condition: $.status.phase != 'Pending'
      type: jsonpath
    outputs:
      phase: $response.body#/status/phase
      startTime: $response.body#/status/startTime
      nodeName: $response.body#/spec/nodeName
  - stepId: collectTaskLog
    description: >-
      Read the container log as the task's output. This is the only place the
      command's stdout is retained once the pod is deleted.
    operationId: readNamespacedPodLog
    parameters:
    - name: namespace
      in: path
      value: $inputs.namespace
    - name: name
      in: path
      value: $steps.createTaskPod.outputs.podName
    - name: container
      in: query
      value: $inputs.taskName
    - name: follow
      in: query
      value: false
    - name: tailLines
      in: query
      value: $inputs.tailLines
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      logOutput: $response.body
  - stepId: cleanupTaskPod
    description: >-
      Delete the completed task pod so finished one-off runs do not accumulate.
      The log has already been collected by the previous step.
    operationId: deleteNamespacedPod
    parameters:
    - name: namespace
      in: path
      value: $inputs.namespace
    - name: name
      in: path
      value: $steps.createTaskPod.outputs.podName
    - name: gracePeriodSeconds
      in: query
      value: 0
    successCriteria:
    - condition: $statusCode == 200
    outputs:
      deletionTimestamp: $response.body#/metadata/deletionTimestamp
  outputs:
    podName: $steps.createTaskPod.outputs.podName
    phase: $steps.pollTaskPod.outputs.phase
    logOutput: $steps.collectTaskLog.outputs.logOutput