Skip to content
Open
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
77 changes: 66 additions & 11 deletions docs/unikernel-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ the cloud-native ecosystem. For that reason, `urunc` aims to support all the
available unikernel frameworks and similar technologies.

For the time being, `urunc` provides support for
[Unikraft](https://unikraft.org/) and
[Rumprun](https://github.com/cloudkernels/rumprun) unikernels.
[Unikraft](https://unikraft.org/),
[Rumprun](https://github.com/cloudkernels/rumprun) and
[OSv](https://github.com/cloudius-systems/osv)
unikernels.

## Unikraft

Expand Down Expand Up @@ -275,6 +277,68 @@ sudo nerdctl run -m 512M --rm -ti --runtime io.containerd.urunc.v2 harbor.nbfc.i

> Note: As far as we understand, Mewz requires at least 512M of memory to properly boot.

## OSv

[OSv](https://github.com/cloudius-systems/osv) is a specialized operating
system designed specifically to run as a single application on top of a
hypervisor. Unlike traditional unikernel frameworks that require significant
application modifications, [OSv](https://github.com/cloudius-systems/osv)
provides strong POSIX compatibility and supports unmodified applications written
in various programming languages including Java, Node.js, Python, Ruby, and Go.

[OSv](https://github.com/cloudius-systems/osv) was designed with cloud
environments in mind, optimizing for minimal overhead and fast boot times.
It includes a built-in ZFS filesystem for reliable storage and provides
efficient memory management tailored for single-application workloads. The
framework is particularly well-suited for database applications, microservices,
and other cloud-native workloads that benefit from reduced OS overhead.

One of the key advantages of [OSv](https://github.com/cloudius-systems/osv) is
its ability to run complex applications with minimal modification. Applications
that depend on threading, networking, and file I/O work seamlessly on
[OSv](https://github.com/cloudius-systems/osv), making it an excellent choice
for migrating existing applications to a unikernel environment.

### VMMs and other sandbox monitors

[OSv](https://github.com/cloudius-systems/osv) is designed to run on KVM-based
hypervisors and supports [Qemu](https://www.qemu.org/) as its primary VMM.
It leverages standard virtio drivers for both networking (virtio-net) and
storage (virtio-blk), providing high-performance I/O operations.

[OSv](https://github.com/cloudius-systems/osv) takes full advantage of
hardware virtualization extensions and is optimized for KVM, delivering
near-native performance for many workloads. The framework includes support for
multiple virtual CPUs and can efficiently utilize available hardware resources.

### OSv and `urunc`

In the case of [OSv](https://github.com/cloudius-systems/osv), `urunc` provides
support for [Qemu](https://www.qemu.org/). When configured with network access,
`urunc` automatically sets up virtio-net devices for
[OSv](https://github.com/cloudius-systems/osv) unikernels with proper IP
configuration including address, netmask, and gateway settings.

For storage, `urunc` supports attaching block devices to
[OSv](https://github.com/cloudius-systems/osv) unikernels using virtio-blk.
[OSv](https://github.com/cloudius-systems/osv)'s built-in ZFS filesystem can
be used to provide reliable and efficient storage for applications.

Network and environment variable configuration is passed to
[OSv](https://github.com/cloudius-systems/osv) through its command-line
interface, allowing seamless integration with container orchestration platforms.

For more information on packaging
[OSv](https://github.com/cloudius-systems/osv) unikernels for `urunc`, take
a look at our [packaging](../package/) page.

An example of [OSv](https://github.com/cloudius-systems/osv) on top of
[Qemu](https://qemu.org) with `urunc`:

```bash
sudo nerdctl run --rm -ti --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/httpserver-qemu-osv:latest
```

## Linux

[Linux](https://github.com/torvalds/linux) is maybe the most widely used kernel
Expand Down Expand Up @@ -341,12 +405,3 @@ An example of a Redis alpine image transformed to a block file on top of
```bash
sudo nerdctl run --rm -ti --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/redis-firecracker-linux-block:latest
```

## Future unikernels and frameworks:

In the near future, we plan to add support for the following frameworks:

[OSv](https://github.com/cloudius-systems/osv): An OS designed specifically to
run as a single application on top of a hypervisor. OSv is known for its
performance optimization and supports a wide range of programming languages,
including Java, Node.js, and Python.
149 changes: 149 additions & 0 deletions pkg/unikontainers/unikernels/osv.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
// Copyright (c) 2023-2026, Nubificus LTD
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package unikernels

import (
"fmt"
"strings"

"github.com/urunc-dev/urunc/pkg/unikontainers/types"
)

const OSvUnikernel string = "osv"

type OSv struct {
Command string
Monitor string
Env []string
Net OSvNet
Block []OSvBlock
}

type OSvNet struct {
Address string
Mask string
Gateway string
}

type OSvBlock struct {
ID string
HostPath string
}

func (o *OSv) CommandString() (string, error) {
// OSv accepts command line arguments directly
// Network configuration is passed via --ip, --netmask, and --defaultgw
// Environment variables are passed with --env
cmdString := ""

if o.Net.Address != "" {
cmdString += fmt.Sprintf("--ip=%s ", o.Net.Address)
if o.Net.Mask != "" {
cmdString += fmt.Sprintf("--netmask=%s ", o.Net.Mask)
}
if o.Net.Gateway != "" {
cmdString += fmt.Sprintf("--defaultgw=%s ", o.Net.Gateway)
}
}

for _, env := range o.Env {
cmdString += fmt.Sprintf("--env=%s ", env)
}

if o.Command != "" {
cmdString += "-- " + o.Command
}

return strings.TrimSpace(cmdString), nil
}

func (o *OSv) SupportsBlock() bool {
return true
}

func (o *OSv) SupportsFS(fsType string) bool {
// OSv primarily uses block devices
// It has a built-in ZFS filesystem
switch fsType {
case "zfs":
return true
default:
return false
}
}

func (o *OSv) MonitorNetCli(ifName string, mac string) string {
// OSv uses standard QEMU virtio-net configuration
// The network configuration is handled by QEMU's standard virtio-net device
// No special CLI options needed as QEMU handles this with standard virtio
return ""
}

func (o *OSv) MonitorBlockCli() []types.MonitorBlockArgs {
if len(o.Block) == 0 {
return nil
}

switch o.Monitor {
case "qemu":
// OSv uses virtio-blk for block devices
// Return block device configurations for QEMU
blockArgs := make([]types.MonitorBlockArgs, 0, len(o.Block))
for _, block := range o.Block {
blockArgs = append(blockArgs, types.MonitorBlockArgs{
ID: block.ID,
Path: block.HostPath,
})
}
return blockArgs
default:
return nil
}
}

func (o *OSv) MonitorCli() types.MonitorCliArgs {
// No special monitor CLI arguments needed for OSv
return types.MonitorCliArgs{}
}

func (o *OSv) Init(data types.UnikernelParams) error {
o.Command = strings.Join(data.CmdLine, " ")
o.Monitor = data.Monitor
o.Env = data.EnvVars

// Configure network if provided
if data.Net.Mask != "" {
o.Net.Address = data.Net.IP
o.Net.Gateway = data.Net.Gateway
o.Net.Mask = data.Net.Mask
}

// Configure block devices if provided
if len(data.Block) > 0 {
o.Block = make([]OSvBlock, 0, len(data.Block))
for _, block := range data.Block {
o.Block = append(o.Block, OSvBlock{
ID: block.ID,
HostPath: block.Source,
})
}
}

return nil
}

func newOSv() *OSv {
return &OSv{}
}
3 changes: 3 additions & 0 deletions pkg/unikontainers/unikernels/unikernel.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ func New(unikernelType string) (types.Unikernel, error) {
case LinuxUnikernel:
unikernel := newLinux()
return unikernel, nil
case OSvUnikernel:
unikernel := newOSv()
return unikernel, nil
default:
return nil, ErrNotSupportedUnikernel
}
Expand Down