Skip to content
Draft
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 README.md
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ supported VM/Sandbox monitors and unikernels:
| Mewz | QEMU | x86 | In-memory |
| Linux | QEMU, Firecracker, Cloud-HYpervisor | x86,aarch64 | Initrd, Block/Devmapper, 9pfs, Virtiofs |
| Hermit | QEMU | x86 | Initrd |
| IncludeOS | QEMU, Solo5-hvt, Solo5-spt | x86,aarch64 | Block/Devmapper |

We plan to add support for more unikernel frameworks and other platforms too.
Feel free to [contact](#Contact) us for a specific unikernel framework or similar
Expand Down
3 changes: 3 additions & 0 deletions docs/hypervisor-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ Supported unikernel frameworks with `urunc`:
- [Mewz](../unikernel-support#mewz)
- [Linux](../unikernel-support#linux)
- [Hermit](../unikernel-support#hermit)
- [IncludeOS](../unikernel-support#includeos)

An example unikernel:

Expand Down Expand Up @@ -245,6 +246,7 @@ Supported unikernel frameworks with `urunc`:

- [Rumprun](../unikernel-support#rumprun)
- [MirageOS](../unikernel-support#mirage)
- [IncludeOS](../unikernel-support#includeos)

An example unikernel with a block image inside the container's rootfs:

Expand Down Expand Up @@ -385,6 +387,7 @@ Supported unikernel frameworks with `urunc`:

- [Rumprun](../unikernel-support#rumprun)
- [MirageOS](../unikernel-support#mirage)
- [IncludeOS](../unikernel-support#includeos)

An example unikernel which utilizes devmapper for block storage:

Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ Sandbox monitors, along with the unikernels that can run on top of them.
| [Mewz](./unikernel-support#mewz)| [Qemu](./hypervisor-support#qemu) | x86 | In-memory |
| [Linux](./unikernel-support#linux)| [Qemu](./hypervisor-support#qemu), [Firecracker](./hypervisor-support#aws-firecracker), [Cloud-Hypervisor](./hypervisor-support#cloud-hypervisor) | x86, aarch64 | Initrd, Block/Devmapper, 9pfs, Virtiofs |
| [Hermit](./unikernel-support#hermit)| [Qemu](./hypervisor-support#qemu) | x86 | Initrd |
| [IncludeOS](./unikernel-support#includeos)| [Qemu](./hypervisor-support#qemu), [Solo5-hvt](./hypervisor-support#solo5-hvt), [Solo5-spt](./hypervisor-support#solo5-spt) | x86, aarch64 | Block/Devmapper |

<!-- ## urunc and the CNCF -->

Expand Down
30 changes: 30 additions & 0 deletions docs/unikernel-support.md
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,36 @@ An example of running a Hermit unikernel with `urunc`:
sudo nerdctl run --rm -ti --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/hello-world-qemu-hermit-initrd:latest
```

## IncludeOS

[IncludeOS](https://github.com/includeos/IncludeOS) is an open-source, modular unikernel written in C++ designed for building cloud services and network applications. IncludeOS can execute on top of [Solo5](https://github.com/Solo5/solo5) and [Qemu](https://www.qemu.org/), making it compatible with `urunc` across these monitors.

### VMMs and other sandbox monitors

IncludeOS runs on top of [QEMU](https://www.qemu.org/) as well as [Solo5-hvt](https://github.com/Solo5/solo5) and [Solo5-spt](https://github.com/Solo5/solo5). It accesses the network via standard interfaces:
- **QEMU**: virtio-net
- **Solo5**: Solo5 network interface (`--net:service=...`)

For storage, IncludeOS supports block devices:
- **QEMU**: virtio-blk
- **Solo5**: Solo5 block device interface (`--block:rootfs=...`)

### IncludeOS and `urunc`

In the case of IncludeOS, `urunc` provides support for booting on QEMU, Solo5-hvt, and Solo5-spt. When the container is configured with network access, `urunc` provides the appropriate monitor networking configuration.

An example of running an IncludeOS unikernel with `urunc` on top of QEMU:

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

An example of running an IncludeOS unikernel with `urunc` on top of Solo5-hvt:

```bash
sudo nerdctl run --rm -ti --runtime io.containerd.urunc.v2 harbor.nbfc.io/nubificus/urunc/hello-hvt-includeos:latest
```

## Future unikernels and frameworks:

In the near future, we plan to add support for the following frameworks:
Expand Down
2 changes: 2 additions & 0 deletions docs/variables/versions.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,5 @@ versions:
kubectl: "1.30.0"
calico: "3.28.0"
kubernetes: "1.30"
includeos: "6fd33d3"
nix: "2.35.2"
130 changes: 130 additions & 0 deletions pkg/unikontainers/unikernels/includeos.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// 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 (
"strings"

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

const IncludeosUnikernel string = "includeos"

type IncludeOS struct {
Command string
Monitor string
Net IncludeOSNet
Block []IncludeOSBlock
}

type IncludeOSNet struct {
Address string
Gateway string
Mask string
}

type IncludeOSBlock struct {
ID string
HostPath string
}

func (i *IncludeOS) CommandString() (string, error) {
var parts []string
if i.Net.Address != "" {
parts = append(parts, i.Net.Address, i.Net.Gateway, i.Net.Mask)
}
if i.Command != "" {
parts = append(parts, i.Command)
}
return strings.Join(parts, " "), nil
}

func (i *IncludeOS) SupportsBlock() bool {
return true
}

// SupportsFS returns whether IncludeOS supports shared filesystem mounts (such as 9pfs or virtiofs).
// IncludeOS does not support 9pfs or virtiofs; block storage is handled via SupportsBlock.
func (i *IncludeOS) SupportsFS(_ string) bool {
return false
}

func (i *IncludeOS) MonitorNetCli(ifName string, mac string) string {
switch i.Monitor {
case "hvt", "spt":
netOption := "--net:service=" + ifName
netOption += " --net-mac:service=" + mac
return netOption
case "qemu":
return ""
default:
return ""
}
}

func (i *IncludeOS) MonitorBlockCli() []types.MonitorBlockArgs {
if len(i.Block) == 0 {
return nil
}
switch i.Monitor {
case "hvt", "spt":
return []types.MonitorBlockArgs{
{
ID: "rootfs",
Path: i.Block[0].HostPath,
},
}
case "qemu":
return []types.MonitorBlockArgs{
{
ID: "rootfs",
Path: i.Block[0].HostPath,
},
}
default:
return nil
}
}

func (i *IncludeOS) MonitorCli() types.MonitorCliArgs {
return types.MonitorCliArgs{}
}

func (i *IncludeOS) Init(data types.UnikernelParams) error {
if data.Net.Mask != "" {
i.Net.Address = data.Net.IP
i.Net.Gateway = data.Net.Gateway
i.Net.Mask = data.Net.Mask
}

i.Block = make([]IncludeOSBlock, 0, len(data.Block))
for _, blk := range data.Block {
newBlk := IncludeOSBlock{
ID: blk.ID,
HostPath: blk.Source,
}
i.Block = append(i.Block, newBlk)
}

i.Command = strings.Join(data.CmdLine, " ")
i.Monitor = data.Monitor

return nil
}

func newIncludeos() *IncludeOS {
includeosStruct := new(IncludeOS)
return includeosStruct
}
Loading