Zudoku
Cloud Platform

Volumes

A volume is a persistent storage device that keeps data across restarts. On Unikraft Cloud (UKC), you can initialize a volume through an instance, or you can create one by importing local data, either from a directory, or through a Dockerfile-driven build.

In this guide we will create a volume, attach it to an instance (a web server), and write to it. We will then show how to detach it, kill that instance, and attach it to a new instance, showing that what we wrote to it persisted across instances. Finally, we will discuss how you can share volumes across instances (read-only at present).

Unikraft Cloud also supports sharing a volume across multiple instances, currently only as a read-only mount (read-write for volume sharing is in the works).

Setting Up the Volume

To start, let's create the volume via kraft cloud volume, with size in MBs and name my-volume:

Terminal
kraft cloud volume create --size 100 --name my-volume

The command should return the volume's UUID, and you can check the operation worked via:

Terminal
kraft cloud volume list

which should output something similar to:

Terminal
NAME CREATED AT SIZE ATTACHED TO STATE PERSISTENT my-volume 15 seconds ago 100 MiB available true

Notice the ATTACHED TO field is empty as we haven't attached it to any instances yet.

Populating the Volume with Local Data (Optional)

If you'd like to populate your empty volume with local data, you can use the kraft cloud volume import command. For example, assuming the volume's name is my-volume and that the data you want to import are in your my-data directory, you would run:

Terminal
kraft cloud volume import --volume my-volume --source my-data

You should see output similar to:

Terminal
[+] Packaging source as a CPIO archive... done! [0.0s] [+] Spawning temporary volume data import instance... done! [0.1s] [+] Importing data (256 B) ••••••••••••••••••••••••••••••••••••••••••• 100% [0.1s] [●] Import complete ├─── volume: my-volume ├─ imported: 256 B └─ capacity: 100 MiB

Setting Up the Web Server

We'll use a Flask web server to write to the volume:

Terminal
git clone https://github.com/unikraft-cloud/examples cd examples/http-python3.12-flask3.0

Replace the contents of server.pywith:

server.py
from flask import Flask, send_from_directory from datetime import datetime import os app = Flask(__name__) file_path = "/mnt/log.txt" def initialize_file(): if not os.path.exists(file_path): with open(file_path, 'w') as log_file: log_file.write("Log file created.\n") @app.route('/') def write_to_file(): initialize_file() current_datetime = datetime.now().strftime("%Y-%m-%d %H:%M:%S") # Write to file with open(file_path, 'a') as log_file: log_file.write(f"{current_datetime}\n") # Read contents of the file with open(file_path, 'r') as log_file: file_contents = log_file.read() return file_contents if __name__ == '__main__': app.run(host='0.0.0.0', port=8080)

On every request, this simple server will write a timestamp to a file on the mounted persistent volume and print out the current contents of the file.

With this in place, let's start our Flask web server, create a service for it via the -p flag, and have the instance mount the my-volume volume we created earlier at /mnt:

Terminal
kraft cloud deploy -M 512 -p 443:8080 --volume my-volume:/mnt .

You should see output similar to:

Terminal
[] Deployed successfully! ────────── name: http-python312-flask30-2h608 ────────── uuid: dcaf899e-6831-4641-86a6-e2b39e9f0d98 ───────── state: running ─────────── url: https://holy-bonobo-px345skl.fra0.kraft.host ───────── image: http-python312-flask30@sha256:3ca3e773d5bc76e1231347e5345e19d0293ba05e502e387956ecba39a4c9372c ───── boot time: 219.61 ms ──────── memory: 512 MiB ─────── service: holy-bonobo-px345skl ── private fqdn: http-python312-flask30-2h608.internal ──── private ip: 172.16.6.4 ────────── args: /usr/bin/python3 /app/server.py

To see that the volume is attached, run:

Terminal
kraft cloud volume get my-volume

You should see output similar to:

NAME CREATED AT SIZE ATTACHED TO STATE PERSISTENT my-volume 34 minutes ago 100 MiB http-python312-flask30-2h608 mounted true

Testing it

Our Python Flask server should write the time and date to the volume (more specifically to /mnt/log.txt) each time the server's URL is accessed. To test simply curl the URL multiple times, you should see output similar to:

Terminal
$ curl https://holy-bonobo-px345skl.fra0.kraft.host Log file created. 2024-02-24 08:15:32 $ curl https://holy-bonobo-px345skl.fra0.kraft.host Log file created. 2024-02-24 08:15:32 2024-02-24 08:15:34 $ curl https://holy-bonobo-px345skl.fra0.kraft.host Log file created. 2024-02-24 08:15:32 2024-02-24 08:15:34 2024-02-24 08:15:35

To test that the data (the date and time) were properly written to the persistent volume, let's first stop the instance, detaching the volume, and removing the instance:

Terminal
kraft cloud instance stop http-python312-flask30-2h608 kraft cloud volumes detach my-volume kraft cloud instance rm http-python312-flask30-2h608

Now let's start another instance and, like before, mount the same volume:

Terminal
kraft cloud deploy -M 512 -p 443:8080 --volume my-volume:/mnt .

This should output something similar to:

Terminal
[] Deployed successfully! ────────── name: http-python312-flask30-0s9c7 ────────── uuid: 59d06415-84b8-4bf5-85c7-997960382011 ───────── state: running ─────────── url: https://winter-field-v6m37jgs.fra0.kraft.host ───────── image: http-python312-flask30@sha256:9f441af88df8968b368e7b658737c804fc8be87c864fc2d695e6adcda9a56acf ───── boot time: 202.11 ms ──────── memory: 512 MiB ─────── service: winter-field-v6m37jgs ── private fqdn: http-python312-flask30-0s9c7.internal ──── private ip: 172.16.6.7 ────────── args: /usr/bin/python3 /app/server.py

Do one final curl to this new URL; you should see the contents written by the previous instance on there, plus a new entry at the bottom:

Terminal
$ curl https://holy-bonobo-px345skl.fra0.kraft.host Log file created. 2024-02-24 08:15:32 2024-02-24 08:15:34 2024-02-24 08:15:35 2024-02-24 08:20:58

Clearning Up

To clean up the volume, detach it from all instances and then remove it:

Terminal
kraft cloud volume detach <volume-name> kraft cloud volume remove <volume-name>

Learn More

Last modified on