Skip to content

Configure Arena S3 result storage

Enterprise

Configure an ArenaJob to upload its output files to Amazon S3 or an S3-compatible store such as MinIO.

  • Arena Fleet enabled in your Omnia installation.
  • An existing S3 bucket, or an S3-compatible endpoint reachable from the cluster.
  • Credentials with s3:PutObject on the bucket: a Secret holding an access key, or an IAM role on EKS.

The worker stages its output files locally. When every work item has finished, it uploads them to s3://<bucket>/<prefix>/<run-name>/<relative-path>, so each run of a scheduled ArenaJob keeps its own files.

  1. Choose how workers authenticate.

    Static credentials. Create a Secret in the ArenaJob’s namespace with these two keys. The values below are placeholders:

    apiVersion: v1
    kind: Secret
    metadata:
    name: arena-s3-credentials
    namespace: default
    type: Opaque
    stringData:
    AWS_ACCESS_KEY_ID: "<access-key-id>"
    AWS_SECRET_ACCESS_KEY: "<secret-access-key>"
    Terminal window
    kubectl apply -f s3-credentials.yaml

    IAM roles for service accounts (EKS). Create an IAM policy that allows uploads, and a role that trusts a ServiceAccount:

    {
    "Version": "2012-10-17",
    "Statement": [
    {
    "Effect": "Allow",
    "Action": "s3:PutObject",
    "Resource": "arn:aws:s3:::my-arena-results/*"
    }
    ]
    }

    Annotate that ServiceAccount with the role ARN, then set the chart value enterprise.arena.worker.serviceAccountName to its name. Workers then run as that ServiceAccount. With the value empty, each run gets a generated arena-worker ServiceAccount that has no cloud identity.

    enterprise:
    arena:
    worker:
    serviceAccountName: arena-worker-s3

    The ServiceAccount must exist in the namespace where the ArenaJob runs.

  2. Add output to the ArenaJob. The worker requires region, even for S3-compatible storage. Omit secretRef when you use IAM roles.

    apiVersion: omnia.altairalabs.ai/v1alpha1
    kind: ArenaJob
    metadata:
    name: nightly-eval
    namespace: default
    spec:
    sourceRef:
    name: my-eval-config
    type: evaluation
    workers:
    replicas: 2
    output:
    type: s3
    s3:
    bucket: my-arena-results
    prefix: "evaluations/nightly/"
    region: us-west-2
    secretRef:
    name: arena-s3-credentials
  3. For MinIO or another S3-compatible store, add endpoint. The worker addresses buckets by path, so the bucket must already exist. Set region to any non-empty value, such as us-east-1.

    output:
    type: s3
    s3:
    bucket: arena-results
    prefix: "evals/"
    region: us-east-1
    endpoint: http://minio.minio-system.svc:9000
    secretRef:
    name: minio-credentials
  4. Apply the ArenaJob.

    Terminal window
    kubectl apply -f arenajob.yaml
  1. Find the run and wait for it to finish.

    Terminal window
    kubectl get arenaruns -l omnia.altairalabs.ai/arena-job=nightly-eval
  2. Check the OutputPersisted condition. True names the destination.

    Terminal window
    kubectl get arenarun <run-name> \
    -o jsonpath='{.status.conditions[?(@.type=="OutputPersisted")]}'
  3. List the bucket.

    Terminal window
    aws s3 ls s3://my-arena-results/evaluations/nightly/<run-name>/ --recursive

The upload contains the files the Arena engine writes to its output directory: media files, session recordings if the arena config enables them, and the data file of a datagen run. Per-scenario evaluation results are recorded in session-api, so a text-only evaluation can upload nothing.

The run succeeds but nothing is in the bucket

Section titled “The run succeeds but nothing is in the bucket”

An upload failure does not fail the run. It sets OutputPersisted=False with reason OutputUploadFailed and emits a Warning event of the same reason; the message carries the first error. The worker logs it as output upload failed.

Terminal window
kubectl describe arenarun <run-name>

Set spec.output.s3.region.

Confirm the credentials or role allow s3:PutObject on <bucket>/<prefix>*. If the Secret lacks AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY, the worker ignores it and falls back to the default AWS credential chain.

Confirm the endpoint is reachable from the worker pods, uses http:// for a non-TLS service, and names an existing bucket.