My FeedDiscussionsHeadless CMS
New
Sign in
Log inSign up
Learn more about Hashnode Headless CMSHashnode Headless CMS
Collaborate seamlessly with Hashnode Headless CMS for Enterprise.
Upgrade ✨Learn more
OPS - Easily Build and Run Unikernels on Mac/Linux

OPS - Easily Build and Run Unikernels on Mac/Linux

Ian Eyberg's photo
Ian Eyberg
·Jan 22, 2019

Unikernels have drifted in and out of devops conversations about what is coming down the pipeline, however, for the majority of developers they have been in-accessible due to their complexity and their low level nature. Most implementations are written in esoteric languages or involve lots of low level c programming - just simply not something that your average developer is going to be exposed to.

Real quick - you can think of a unikernel as a way of deploying your application as it's own little operating system. Unlike Linux that is a general purpose operating system a unikernel is specially designed to run only one program - yours. Engineers find this interesting because it means you can run your code faster, more secure and since they are roughly the size of your application you can run a lot of them. Some people think of them as containers++ or containers 2.0, although personally I don't think they are anything like containers but that's just me.

OPS is a project designed to fix the problems of allowing everyone to build and run unikernels. It is specifically designed to have a focus on ease of use while at the same time embracing unikernel concepts. OPS allows anyone - including those that don't code to build and run linux programs as unikernels.

Want to get started? Ok.

The first thing you want to do is install OPS. You can download the binary like this or goto the source .

curl https://ops.city/get.sh -sSfL | sh

From there let's try a php example.

If we plop this into example.php

  <?php
      phpinfo();
   ?>

We can run it like this:

  $ ops load php_7.2.13 -a example.php

What this will do is download a base package that has a nice install of php bundled up ready to go. If you are feeling adventurous you can even create these packages yourself but to get started will just use a pre-made one.

What this does is load your example.php onto a filesystem that it creates on the fly along with everything php wants/needs to run it. Then it spins up qemu to run it as a virtual machine.

What we are doing here is basically mimicking what happens in the cloud providers like GCE and AWS. In fact they use private forks of KVM to power their clouds. It's important to note that in this example we are not using KVM and we are in what's called 'usermode' networking. It's definitely slower but you can also enable KVM acceleration by running this on linux or installing Intel HAX.

Want to try a larger example? How about a go web server?

Put this into a main.go:

 package main

  import (
      "log"
      "net/http"
  )

  func main() {
      fs := http.FileServer(http.Dir("static"))
      http.Handle("/", fs)

      log.Println("Listening...on 8080")
      http.ListenAndServe(":8080", nil)
  }

Now let's build it like we are going to deploy it to a linux server. It's important to note that OPS doesn't actually run linux - it runs linux binaries. It can do this because it speaks the POSIX standard (loosely). However, there are definitely certain things that linux does that it will never do and that's by design.

  $ GOOS=linux go build main.go

Once we have it built we can go ahead and create a static folder with a index.html in it:

mkdir static
cd static

Throw this in to index.html :

  <!doctype html>
  <html>
  <head>
  <meta charset="utf-8">
      <title>A static page</title>
  </head>
  <body>
      <h1>Hello from a static page</h1>
  </body>
  </html>

Now we are going to show some of the config.json functionality:

{
      "Dirs" : ["static"]
 }

In this example what we've told OPS is to stuff the static directory onto it's filesystem as it is building the virtual machine image. Keep in mind we are converting your program into a 'virtual machine' - so that's the same thing as an AWS AMI or GCE image. (In fact you'll see that as a deploy option in the near future.)

From there you can build && run it:

  $ ops run -p 8080 -c config.json server

What this does is open up port 8080 and run the app. Now you should be able to hit the webserver:

  curl http://localhost:8080/hello.html

You just built your own bootable operating system which only has your application inside of it.

Want to see something even cooler?

If you compare the 'image' filename to the 'main' binary you see the difference? You've got a VM clocking in at just over 8M which is still roughly the size of your go webserver.

 ls -lh
total 29752
-rw-r--r--  1 eyberg  staff   8.2M Jan 22 14:50 image
-rwxr-xr-x  1 eyberg  staff   6.3M Jan 22 14:50 main
-rw-r--r--  1 eyberg  staff   198B Jan 22 13:27 main.go

OPS has a lot more functionality in it than what we exposed in this article and the ecosystem is growing by the day with more packages and better support.

It's worth your time investigating unikernels. The big cloud providers have made it pretty clear that they are prepping for massive adoption of these types of systems with gVisor from Google and Firecracker from AWS. While these are not unikernels per-se they are very heavy indications of what is coming down the pipeline.

I'm personally very excited about the new forms of compute that unikernels open up because of their size, performance, and security implications. I think they'll play a bit part in serverless runtimes, edge compute and many other interesting ecosystems.