Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions frontend/src/types/backend.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ declare type TBackendType =
| 'crusoe'
| 'cudo'
| 'datacrunch'
| 'daytona'
| 'dstack'
| 'gcp'
| 'kubernetes'
Expand Down
4 changes: 2 additions & 2 deletions frontend/src/types/volume.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ declare interface IVolumeConfiguration {
type: "volume",
name?: string,
backend: TBackendType,
region: string,
region?: string,
size?: number,
volume_id?: string
}

declare interface IVolumeProvisioningData {
backend?: TBackendType,
volume_id: string,
size_gb: number,
size_gb: number | null,
availability_zone?: string
price?:number
attachable: boolean
Expand Down
28 changes: 28 additions & 0 deletions mkdocs/docs/concepts/backends.md
Original file line number Diff line number Diff line change
Expand Up @@ -1473,6 +1473,34 @@ projects:
- **Runs always execute as `root`.** `enroot` is a single-user container runtime: it can only map the invoking host user inside the container to either the same UID/GID or to `root` (`0:0`). `dstack` uses the latter, so runs always execute as `root`, and both the image's default user and the run configuration's `user` property are ignored. The single-user model is a fundamental `enroot` limitation, not specific to the `dstack` integration.
- **Private registries via `registry_auth` are not supported.** The `registry_auth` run configuration property is rejected. You can still pull images from a private registry by preconfiguring `enroot` credentials on the cluster's compute nodes — see the [enroot import documentation](https://github.com/NVIDIA/enroot/blob/main/doc/cmd/import.md#description).

### Daytona

Create an API key in the [Daytona dashboard](https://app.daytona.io/) for the organization
that will own the sandboxes. Then configure the backend:

<div editor-title="~/.dstack/server/config.yml">

```yaml
projects:
- name: main
backends:
- type: daytona
creds:
type: api_key
api_key: YOUR_DAYTONA_API_KEY
```

</div>

??? info "Required permissions"
The API key requires `write:sandboxes`, `delete:sandboxes`, and `read:limits`.

Additional permissions depend on the features used:

* Private images: `write:registries` and `delete:registries`
* Creating volumes: `read:volumes`, `write:volumes`, and `delete:volumes`
* Registering existing volumes: `read:volumes`

### Runpod

Log into your [Runpod](https://www.runpod.io/console/) console, click Settings in the sidebar, expand the `API Keys` section, and click
Expand Down
27 changes: 20 additions & 7 deletions mkdocs/docs/concepts/volumes.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Useful as a cache for cloud fleets or for persistent storage with SSH fleets.

## Network volumes

> Network volumes are currently supported for the `aws`, `gcp`, `runpod`, and `kubernetes` backends.
> Network volumes are currently supported for the `aws`, `gcp`, `runpod`, `kubernetes`, and `daytona` backends.
### Apply a configuration

Expand All @@ -42,6 +42,16 @@ size: 100GB
If you use this configuration, `dstack` will create a new volume based on the specified options.

??? info "Daytona"
Daytona volumes use [S3-backed FUSE storage](https://www.daytona.io/docs/en/volumes/).
Storage grows with usage, and the same volume can be mounted in any Daytona region.

```yaml
type: volume
backend: daytona
name: my-volume
```

??? info "Kubernetes"
Set `region` to a kubeconfig context name enabled in the [backend configuration](backends.md#kubernetes).
Omit it only for legacy configurations without `contexts`.
Expand Down Expand Up @@ -86,7 +96,7 @@ Volume my-volume does not exist yet. Create the volume? [y/n]: y

Once created, the volume can be attached to dev environments, tasks, and services.

> When creating a new network volume, `dstack` automatically creates an `ext4` filesystem on it.
> When creating a new network volume in AWS or GCP, `dstack` automatically creates an `ext4` filesystem on it.

#### Register existing volumes

Expand All @@ -110,7 +120,7 @@ volume_id: vol1235

</div>

If you register an existing volume, you must ensure the volume already has a filesystem.
If you register an existing volume in AWS or GCP, you must ensure the volume already has a filesystem.

??? info "Kubernetes"

Expand Down Expand Up @@ -254,27 +264,30 @@ If you've registered an existing volume, it will be de-registered with `dstack`

??? info "Can I use network volumes across backends?"

Since volumes are backed up by cloud network disks, you can only use them within the same cloud. If you need to access
Volumes can only be used with their backend. If you need to access
data across different backends, you should either use object storage or replicate the data across multiple volumes.

??? info "Can I use network volumes across regions?"

Typically, network volumes are associated with specific regions, so you can't use them in other regions. Often,
volumes are also linked to availability zones, but some providers support volumes that can be used across different
availability zones within the same region.

If you don't want to limit a run to one particular region, you can create different volumes for different regions
and specify them for the same mount point as [documented above](#attach-network-volume).

Daytona volumes can be mounted in any Daytona region.

??? info "Can I attach network volumes to multiple runs or instances?"
You can mount a volume in multiple runs. This feature is currently supported only by the `runpod` backend.
The `runpod` and `daytona` backends support mounting the same volume in multiple runs at the same time.
For `kubernetes`, the storage class and access modes must support sharing, such as `ReadWriteMany`.

## Instance volumes

Instance volumes allow mapping any directory on the instance where the run is executed to any path inside the container.
This means that the data in instance volumes is persisted only if the run is executed on the same instance.

> Instance volumes are currently supported for all backends except `runpod` and `vastai`, and can also be used with [SSH fleets](fleets.md#ssh-fleets).
> Instance volumes are currently supported for all backends except `daytona`, `runpod`, and `vastai`, and can also be used with [SSH fleets](fleets.md#ssh-fleets).
### Attach a volume

Expand Down
8 changes: 8 additions & 0 deletions mkdocs/docs/reference/dstack.yml/volume.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,14 @@ The `volume` configuration type allows creating, registering, and updating [volu
backend:
required: true

=== "Daytona"

#SCHEMA# dstack._internal.core.models.volumes.DaytonaVolumeConfiguration
overrides:
show_root_heading: false
backend:
required: true

=== "Kubernetes"

Kubernetes backend volumes are mapped to [`PersistentVolumeClaim`](https://kubernetes.io/docs/concepts/storage/persistent-volumes/#persistentvolumeclaims) objects.
Expand Down
17 changes: 17 additions & 0 deletions mkdocs/docs/reference/server/config.yml.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ to configure [backends](../../concepts/backends.md) and other [server-level sett
type:
required: true

##### `projects[n].backends[type=daytona]` { #daytona data-toc-label="daytona" }

#SCHEMA# dstack._internal.core.backends.daytona.models.DaytonaBackendConfigWithCreds
overrides:
show_root_heading: false
type:
required: true
item_id_prefix: daytona-

###### `projects[n].backends[type=daytona].creds` { #daytona-creds data-toc-label="creds" }

#SCHEMA# dstack._internal.core.backends.daytona.models.DaytonaAPIKeyCreds
overrides:
show_root_heading: false
type:
required: true

##### `projects[n].backends[type=gcp]` { #gcp data-toc-label="gcp" }

#SCHEMA# dstack._internal.core.backends.gcp.models.GCPBackendConfigWithCreds
Expand Down
3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ dependencies = [
"python-multipart>=0.0.16",
"filelock",
"psutil",
"gpuhunt==0.1.30",
"gpuhunt==0.1.31",
"argcomplete>=3.5.0",
"ignore-python>=0.2.0",
"apscheduler<4",
Expand Down Expand Up @@ -110,6 +110,7 @@ include = [
"src/dstack/_internal/server",
"src/dstack/_internal/core/services",
"src/dstack/_internal/core/backends/aws",
"src/dstack/_internal/core/backends/daytona",
"src/dstack/_internal/core/backends/kubernetes",
"src/dstack/_internal/core/backends/runpod",
"src/dstack/_internal/core/backends/slurm",
Expand Down
10 changes: 6 additions & 4 deletions src/dstack/_internal/cli/services/configurators/volume.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
AnyVolumeConfiguration,
Volume,
VolumeConfigurationWithRegion,
VolumeConfigurationWithSize,
VolumePlan,
VolumeSpec,
VolumeStatus,
Expand Down Expand Up @@ -204,17 +205,18 @@ def th(s: str) -> str:
configuration_table.add_row(th("Type"), plan.spec.configuration.type)

volume_type = "managed"
size = "-"
if plan.spec.configuration.size is not None:
size = str(plan.spec.configuration.size)
if plan.spec.configuration.is_external:
volume_type = "external"

configuration_table.add_row(th("Volume type"), volume_type)
configuration_table.add_row(th("Backend"), plan.spec.configuration.backend.value)
if isinstance(plan.spec.configuration, VolumeConfigurationWithRegion):
configuration_table.add_row(th("Region"), plan.spec.configuration.region)
configuration_table.add_row(th("Size"), size)
if isinstance(plan.spec.configuration, VolumeConfigurationWithSize):
size = "-"
if plan.spec.configuration.size is not None:
size = str(plan.spec.configuration.size)
configuration_table.add_row(th("Size"), size)

console.print(configuration_table)
console.print()
Expand Down
7 changes: 7 additions & 0 deletions src/dstack/_internal/core/backends/configurators.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@
except ImportError:
pass

try:
from dstack._internal.core.backends.daytona.configurator import DaytonaConfigurator

_CONFIGURATOR_CLASSES.append(DaytonaConfigurator)
except ImportError:
pass

try:
from dstack._internal.core.backends.digitalocean.configurator import (
DigitalOceanConfigurator,
Expand Down
Empty file.
Loading
Loading