Up and Running with lx-brand Zones on SmartOS

SmartOS provides a lot of tools for complete virtualization as well as providing Linux compatibility for ease of use with your existing Linux binaries

If you read these regularly, you might know that I recently rebuild a significant portion of my development environment to run SmartOS — this means I can run things like KVM machines, SmartOS zones, and — the topic of this post, and a personal favorite-the lx-brand zone, and am very enthusiastic about this suite of options available to me.

Basically, lx-brand zones allow you to provide a Linux binary with a compatible environment in a non-global (similar, conceptually, to using a Docker container or BSD jail — you’re effectively referring to some isolated process largely outside of the other processes’ visibility) zone on your illumos host (in my case SmartOS).

Creating a zone is a pretty frictionless process manually:

For our usage, we want to provide an Ubuntu 16.04 environment, so I might target images matching that description in imgadm :

[root@compute-01.wbu1 /opt/specs]# imgadm avail | grep ubuntu-16.04

49b22aec-0c8a-11e6-8807-a3eb4db576ba ubuntu-16.04 20160427 linux lx-dataset 2016-04-27

675834a0-1267-11e6-81fe-2b1280d24244 ubuntu-16.04 20160505 linux lx-dataset 2016-05-05

4edaa46a-1b83-11e6-b863-3fb0064133ee ubuntu-16.04 20160516 linux lx-dataset 2016-05-16

05140a7e-279f-11e6-aedf-47d4f69d2887 ubuntu-16.04 20160601 linux lx-dataset 2016-06-01

e331b22a-89d8-11e6-b891-936e4e1caa46 ubuntu-16.04 20161004 linux lx-dataset 2016-10-04

8879c758-c0da-11e6-9e4b-93e32a67e805 ubuntu-16.04 20161213 linux lx-dataset 2016-12-13

7b5981c4-1889-11e7-b4c5-3f3bdfc9b88b ubuntu-16.04 20170403 linux lx-dataset 2017-04-03

8220edab-1c4a-46e0-aa52-08171b8af808 ubuntu-16.04-rancheragent 1.0.0 linux zvol 2017-11-15

3b6828a9-46b2-46f4-bbbb-a5511a3b185c ubuntu-16.04-rancherserver 1.0.0 linux zvol 2017-11-15

Particularly important is that, since we want to build a zone, and not a KVM machine, the type field will be important — we’ll want to select an image of the lx-dataset type rather than a zvol for a full virtual machine.

We can, then, import that image:

imgadm import 7b5981c4-1889-11e7-b4c5-3f3bdfc9b88b

then create a zone from a spec:

[root@compute-01.wbu1 /opt/specs]# cat lx-spec.json << EOF

{

"brand": "lx",

"kernel_version": "3.16.0",

"image_uuid": "7b5981c4-1889-11e7-b4c5-3f3bdfc9b88b",

"alias": "lx-app",

"hostname": "lx-app",

"max_physical_memory": 512,

"quota": 3000,

"resolvers": ["8.8.8.8"],

"nics": [

{

"nic_tag": "admin",

"ip": "dhcp"

}

]

}

EOF [root@compute-01.wbu1 /opt/specs]# vmadm create -f lx-spc.json

Successfully created VM 4d6b19a0-16f1-4b37-a1bb-b3a254a46c48

where you make declarations on things like memory, the kernel version to provide support for, any networking changes, etc.

Grab your zone ID (bolded above — mine was, for example, 4d6b19a0–16f1–4b37-a1bb-b3a254a46c48), and use zlogin to attach to it:

zlogin -l root <zone ID>

You can, for example, run commands without attaching to a shell, using space-delimited arguments, like:

[root@compute-01.wbu1 /opt/specs]# zlogin -l root 4d6b19a0-16f1-4b37-a1bb-b3a254a46c48 uname -rsi

Linux 3.16.0 x86_64

and then you can deploy an application to this zone as you might any other environment like this.

When you create a zone, it creates a filesystem tree in your zones volume, usually, if you used the default upon installation, SmartOS created your zpool on /zones , so you’d see a filesystem for your zone in /zones/<zone ID>/root and then a series of relative paths like you might on any Linux system:

[root@compute-01.wbu1 /opt/specs]# ls /zones/4d6b19a0-16f1-4b37-a1bb-b3a254a46c48/root

bin boot dev etc home lib lib64 media mnt native opt proc root run sbin srv sys system tmp usr var

So, let’s say we have this program, test.py :

import os os.system("uname -rsi")

and want to run it in the zone, we can do something like this to place it in /root/test.py on the zone’s filesystem:

[root@compute-01.wbu1 /opt/specs]# cp test.py /zones/4d6b19a0-16f1-4b37-a1bb-b3a254a46c48/root/root/test.py

and then have the zone execute this command:

[root@compute-01.wbu1 /opt/specs]# zlogin -l root 4d6b19a0-16f1-4b37-a1bb-b3a254a46c48 python3 /root/test.py

Linux 3.16.0 x86_64

One thing I like to do to from here is automate this process, and wrap tasks like these into scripts, and make quickstarting these zones and pre-loading applications pretty trivial. There is also some specialized tooling for common Config Management tools like SaltStack which can be used on branded zones:

which makes keeping this manual work we just went through more and more reproducible (so you don’t need to do things like grab and cache image IDs, zone IDs, and then shuffle things around — in Saltstack this is part of your state, and in other config management paradigms, there’ll be similar instantiation of your data if you use these tools to manage filesystems, etc. in the zone as well).

Similarly, Ansible has support for image management across the various brand types available to SmartOS users:

With that in mind, if you’re running your own virtualization for a development or production environment, and have not tried SmartOS yet, zones are (themselves, regardless of brand, etc.) one potential solution for a lot of different challenges. With common tooling having support for, frankly, the most finicky parts to script automation around (tracking image and instance IDs), these are functions of illumos that could drop right into place into many kinds of environments and architectures.