Skip to main content

Deploy Anyscale on Nebius

Deploy Anyscale on Nebius

This page describes how to deploy a new Anyscale cloud on Managed Service for Kubernetes on Nebius AI Cloud, using Nebius Object Storage as S3-compatible storage for cluster logs, snapshots, and artifacts.

Requirements

Before you start, ensure that you meet the following requirements:

  • You're an Anyscale organization owner.
  • You have an Anyscale account and a Nebius AI Cloud account.
  • The following CLI tools are installed: Anyscale CLI, Nebius AI Cloud CLI, AWS CLI, kubectl, helm, and jq.

Step 1: Create and configure Nebius resources

Anyscale requires the following Nebius resources and configurations:

  • A Managed Service for Kubernetes cluster.
  • A CPU node group.
  • A GPU node group (optional, for GPU workloads).
  • An Object Storage bucket (S3-compatible) for Anyscale system storage.
  • A kubeconfig that can access your cluster.

You need admin permissions in your Nebius account to create and configure these resources.

Create a Kubernetes cluster

Follow the Nebius docs to create your first cluster and node group. Configure a public endpoint for the control plane so you can reach it from your machine and from Anyscale.

Copy the cluster ID from the Nebius console or CLI output for later use with kubectl and helm:

Create a CPU node group

Create a CPU node group for general workloads such as the Anyscale operator and Ray head nodes. In the Nebius node group docs, create a node group with a CPU platform and preset that matches your needs (for example, cpu-d3 with the 4vcpu-16gb preset).

Create a GPU node group (optional)

If you need GPUs, add a GPU node group to the same cluster. See Creating and modifying node groups and Setting up GPUs.

Create and configure a Nebius Object Storage bucket

Create a Nebius Object Storage bucket to use as default system storage for your Anyscale cloud. Anyscale uses this bucket to store assets such as logs, workspace snapshots, and checkpoints.

Capture the following Nebius identifiers for use throughout this guide. You can find your project ID and tenant ID in the Nebius console.

Complete the following steps:

  1. Set the project and create a service account. From the Nebius CLI (after nebius profile create and signing in), create a service account and add it to the editors group so it can create and manage Object Storage buckets:

    nebius config set parent-id <your_project_id>

    export NB_SA_ID=$(nebius iam service-account create \
    --name object-storage-sa --format json \
    | jq -r '.metadata.id')

    export NB_EDITORS_GROUP_ID=$(nebius iam group get-by-name \
    --name editors --parent-id <your_tenant_id> --format json \
    | jq -r '.metadata.id')

    nebius iam group-membership create \
    --parent-id $NB_EDITORS_GROUP_ID \
    --member-id $NB_SA_ID
  2. Create an access key and capture credentials. Nebius access keys don't expire by default. For production deployments, Anyscale recommends setting an expiration with the --expires-at flag and rotating keys before they expire.

    export NB_ACCESS_KEY_ID=$(nebius iam access-key create \
    --account-service-account-id $NB_SA_ID \
    --description 'Anyscale Object Storage' \
    --format json | jq -r '.resource_id')

    export NB_ACCESS_KEY_AWS_ID=$(nebius iam access-key get-by-id \
    --id $NB_ACCESS_KEY_ID \
    --format json | jq -r '.status.aws_access_key_id')

    export NB_SECRET_ACCESS_KEY=$(nebius iam access-key get-secret-once \
    --id $NB_ACCESS_KEY_ID --format json \
    | jq -r '.secret')

    echo NB_ACCESS_KEY_AWS_ID;
    echo NB_SECRET_ACCESS_KEY;

    Capture the output for your Nebius access key ID and your access key secret in the following fields:

  3. Configure the AWS CLI for Nebius. Nebius Object Storage is S3-compatible. In this step, you add a nebius profile to your ~/.aws/config file so you can use the AWS CLI to manage your Nebius Object Storage bucket.

    Choose a name for your bucket and provide the Nebius region where your cluster is located, for example eu-north1.

    [profile nebius]
    aws_access_key_id=<access_key_id>
    aws_secret_access_key=<access_key_secret>
    region=<your_bucket_region>
    endpoint_url=https://storage.<your_bucket_region>.nebius.cloud:443
    s3 =
    addressing_style = virtual
  4. Create the bucket on Nebius Object Storage. This command uses the AWS CLI as an S3-compatible client. Because the nebius profile points at the Nebius endpoint, the bucket is created on Nebius — not on AWS.

    aws s3 mb s3://<your_bucket_name> --profile nebius
  5. Enable CORS for your bucket. Anyscale requires CORS on your Object Storage bucket. Create a file named cors.json with the following contents:

    {
    "CORSRules": [
    {
    "AllowedOrigins": ["https://*.anyscale.com"],
    "AllowedMethods": ["GET", "PUT", "POST", "DELETE", "HEAD"],
    "AllowedHeaders": ["*"],
    "ExposeHeaders": ["Accept-Ranges", "Content-Range", "Content-Length"],
    "MaxAgeSeconds": 3600
    }
    ]
    }

    Apply the CORS configuration to your bucket:

    aws s3api put-bucket-cors \
    --bucket <your_bucket_name> \
    --cors-configuration file://cors.json \
    --profile nebius

Connect to the cluster

Create a kubeconfig so you can run kubectl and helm against your cluster:

nebius mk8s cluster get-credentials --id <your_cluster_id> --external

Verify that you can reach the cluster and that your bucket is accessible:

kubectl get nodes
aws s3 ls s3://<your_bucket_name> --profile nebius

Step 2: Configure ingress for your cluster

Anyscale requires ingress for features such as workspaces and services. Install the NGINX Ingress controller with the settings Anyscale expects.

Create an ingress values file

Create a file named values-nginx.yaml with the following contents:

controller:
service:
type: LoadBalancer
allowSnippetAnnotations: true
config:
enable-underscores-in-headers: "true"
annotations-risk-level: "Critical"
warning

Anyscale services require allowSnippetAnnotations: true and annotations-risk-level: "Critical", which override ingress-nginx's default protections against CVE-2021-25742. Restrict ingress resource permissions to trusted users only.

tip

If your cluster requires a Nebius-specific load balancer annotation for external access, add the appropriate annotation under controller.annotations. See the Nebius Managed Service for Kubernetes docs for details on your network setup.

Install the ingress controller

Run the following commands:

helm repo add nginx https://kubernetes.github.io/ingress-nginx
helm upgrade ingress-nginx nginx/ingress-nginx \
--version 4.12.1 \
--namespace ingress-nginx \
--values values-nginx.yaml \
--create-namespace \
--install

Step 3: Create an Anyscale service account API key

Anyscale uses a service account API key to establish a trust relationship between the Anyscale operator and the control plane.

Run the following command to log in to your Anyscale organization:

anyscale login

Run the following command to confirm your identity and permissions. You must have the owner role to register a new cloud.

anyscale auth show

Copy your organization ID from the output:

Provide a human-readable name for the service account. Anyscale recommends that you use a unique service account and API key for this configuration.

anyscale service-account create --name <your_service_account_name>

Anyscale returns an API key for your service account. Copy the value to the following field:

note

Anyscale service account API keys don't expire. Delete an API key or service account to revoke access. See Service accounts and API keys.

Step 4: Create your Anyscale cloud

Register a new Anyscale cloud that points at your Kubernetes cluster and Nebius Object Storage bucket.

Run the following command:

anyscale cloud register --name <your_cloud_name> \
--provider generic \
--region <your_bucket_region> \
--compute-stack k8s \
--cloud-storage-bucket-name s3://<your_bucket_name> \
--cloud-storage-bucket-endpoint https://storage.<your_bucket_region>.nebius.cloud:443

The command output includes the cloud deployment ID. Copy it:

Grant the service account access to your cloud

The Anyscale operator authenticates as the service account you created in the previous step. Grant the service account collaborator access to your cloud so the operator can manage resources without a 403 error.

Create a file named collaborators.yaml with the following contents:

collaborators:
- email: "<your_service_account_name>@org-<your_org_id>.serviceaccount.com"
permission_level: "collaborator"

Run the following command to grant access:

anyscale cloud add-collaborators --cloud <your_cloud_name> --users-file collaborators.yaml

Step 5: Configure and install the Anyscale operator

Create a Helm values file for the Anyscale operator and install it into your cluster.

Create a values file

Create a values.yaml file. The following example uses the values you provided throughout this guide to create a minimum viable configuration for the Anyscale operator. Anyscale recommends that you start with a minimal spec and then customize after you've verified functional behavior.

global:
cloudProvider: generic
cloudDeploymentId: <your_cloud_deployment_id>
auth:
anyscaleCliToken: <your_anyscale_api_key>
aws:
region: <your_bucket_region>

workloads:
serviceAccount:
name: anyscale-operator

credentialMount:
aws:
enabled: true
createSecret:
create: true
accessKeyId: <access_key_id>
secretAccessKey: <access_key_secret>
endpointUrl: https://storage.<your_bucket_region>.nebius.cloud:443
addressingStyle: virtual
signatureVersion: s3v4
warning

Keep your values.yaml and any secrets (tokens, keys) secure. Don't commit them to version control.

Install the Anyscale operator

Run the following commands:

helm repo add anyscale https://anyscale.github.io/helm-charts
helm repo update anyscale
helm upgrade anyscale-operator anyscale/anyscale-operator \
--namespace anyscale-operator \
-f values.yaml \
--create-namespace \
-i

Step 6: Verify your Anyscale cloud

It can take a few minutes for the operator to become ready. Verify the cloud:

anyscale cloud verify --name <your_cloud_name>

Optionally, submit a small job to confirm end-to-end behavior:

anyscale job submit --cloud <your_cloud_name> \
--working-dir https://github.com/anyscale/docs_examples/archive/refs/heads/main.zip \
-- python hello_world.py

Next steps