How to Start LinuxKit on MacOS Xhyve Engine

Posted by tim on Thu, 04 Jul 2019 00:46:53 +0200

On Dockercon 2017, Linux Kit, an architecture that creates the smallest Linux OS image in a container, was released.

Does that sound cool? Several clouds I saw an article on the Internet [about starting LinuxKit on Mac OS with Xhyve]. The best way to learn the tool is to make the best use of it. The author of the original article went back to Austin after the meeting and began to study it on the plane. Next, he went back to Austin. Several clouds Just share this article with you.

First of all, we need to prepare the following environment:

  1. A Mac after 2010 (CPU supports EPT)

  2. OS X 10.10.3 or later

  3. Git Client

  4. Docker running (example 17.04.0-ce-mac7 (16352))

  5. GNU make

  6. GNU tar

  7. Homebrew

After preparation, follow the following steps.

Install Xhyve

The first step is to install Xhyve. Xhyve is a virtual machine operating system running in OSx's Hypervisor. Its architecture allows virtual machines to run in user space. This is what Docker prepared for MAC users. There are many ways to do this, but the simplest is to use Homebrew. Installation on Machine——

$ brew update
$ brew install --HEAD xhyve

After the installation is completed, verify that it runs according to the following code:

$ xhyve -h

If you see the output containing various available flags, you are ready to move on to the next step.

Building Moby

The second step is to build the Moby tool. This tool provides read. Yaml's feature points will be explained in detail later, and a variety of Docker commands will be executed to build Linux OS. If you like, you can now run Image.

This is more convenient than the Moby's Hyperkit project. Kernel and Initrdimages take less time to build than a qcow image, so if you need to repeat Xhyve quickly, this is a good way to do it.

First, CD to any favorite working directory, and Clone Linux Kit repo:

$ git clone https://github.com/linuxkit/linuxkit.git

Next install Moby binary:

$ cd linuxkit
$ make
$ sudo make install

When you're done, you need to be ready to build your first Linux image using LinuxKit.

Customize and build Linux images

After completing these prerequisites, the first image is created. The LinuxKit project includes some examples, some of which also do live Demo in Dockercon. Create a simple image in Onboot that can start Redis instance, which is faster than starting from a complex point of view!

First, start a Yaml file that describes the Linux image, and then pull out the instance to get the basic Docker image and add an entry to Redis.

$ vi linux-redis.yaml
kernel:
image: "linuxkit/kernel:4.9.x"
cmdline: "console=ttyS0 console=tty0 page_poison=1"
init:
- linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
- linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
- linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
- linuxkit/ca-certificates:eabc5a6e59f05aa91529d80e9a595b85b046f935
onboot:
- name: sysctl
image: "linuxkit/sysctl:1f5ec5d5e6f7a7a1b3d2ff9dd9e36fd6fb14756a"
net: host
pid: host
ipc: host
capabilities:
- CAP_SYS_ADMIN
readonly: true
- name: sysfs
image: linuxkit/sysfs:6c1d06f28ddd9681799d3950cddf044b930b221c
- name: binfmt
image: "linuxkit/binfmt:8881283ac627be1542811bd25c85e7782aebc692"
binds:
- /proc/sys/fs/binfmt_misc:/binfmt_misc
readonly: true
- name: format
image: "linuxkit/format:53748000acf515549d398e6ae68545c26c0f3a2e"
binds:
- /dev:/dev
capabilities:
- CAP_SYS_ADMIN
- CAP_MKNOD
- name: mount
image: "linuxkit/mount:d2669e7c8ddda99fa0618a414d44261eba6e299a"
binds:
- /dev:/dev
- /var:/var:rshared,rbind
capabilities:
- CAP_SYS_ADMIN
rootfsPropagation: shared
command: ["/mount.sh", "/var/lib/docker"]
services:
- name: rngd
image: "linuxkit/rngd:3dad6dd43270fa632ac031e99d1947f20b22eec9"
capabilities:
- CAP_SYS_ADMIN
oomScoreAdj: -800
readonly: true
- name: dhcpcd
image: "linuxkit/dhcpcd:57a8ef29d3a910645b2b24c124f9ce9ef53ce703"
binds:
- /var:/var
- /tmp/etc:/etc
capabilities:
- CAP_NET_ADMIN
- CAP_NET_BIND_SERVICE
- CAP_NET_RAW
net: host
oomScoreAdj: -800
- name: ntpd
image: "linuxkit/openntpd:a570316d7fc49ca1daa29bd945499f4963d227af"
capabilities:
- CAP_SYS_TIME
- CAP_SYS_NICE
- CAP_SYS_CHROOT
- CAP_SETUID
- CAP_SETGID
net: host
- name: redis
image: "redis:3.0.7-alpine"
capabilities:
- CAP_NET_BIND_SERVICE
- CAP_CHOWN
- CAP_SETUID
- CAP_SETGID
- CAP_DAC_OVERRIDE
net: host
files:
- path: etc/docker/daemon.json
contents: '{"debug": true}'
trust:
image:
- linuxkit/kernel
outputs:
- format: kernel+initrd

Now take a quick look at this file. Before going into more detail (as you can see in the Linux Kit git repo), we will focus on the following points——

The first part is the "base" image, which defines Kernel and Kernel command line parameters.

Next, there are some OCI-compatible Linux Kit images required by Init; then, there is the Onboot section, which describes other basic images that need to be started by RunC sequence before other services are started.

Then there's Services, also OCI-compatible mirrors, which are started and maintained by Container.

Finally, specify the output file information that Moby will create during the build process. Next, build the mirror.

$ moby build linux-redis

The following output information is visible——

Extract kernel image: linuxkit/kernel:4.9.x
Add init containers:
Process init image: linuxkit/init:63eed9ca7a09d2ce4c0c5e7238ac005fa44f564b
Process init image: linuxkit/runc:b0fb122e10dbb7e4e45115177a61a3f8d68c19a9
Process init image: linuxkit/containerd:18eaf72f3f4f9a9f29ca1951f66df701f873060b
Process init image: linuxkit/ca-certificates:eabc5a6e59f05aa91529d80e9a595b85b046f935
Add onboot containers:
Create OCI config for linuxkit/sysctl:1f5ec5d5e6f7a7a1b3d2ff9dd9e36fd6fb14756a
Create OCI config for linuxkit/sysfs:6c1d06f28ddd9681799d3950cddf044b930b221c
Create OCI config for linuxkit/binfmt:8881283ac627be1542811bd25c85e7782aebc692
Create OCI config for linuxkit/format:53748000acf515549d398e6ae68545c26c0f3a2e
Create OCI config for linuxkit/mount:d2669e7c8ddda99fa0618a414d44261eba6e299a
Add service containers:
Create OCI config for linuxkit/rngd:3dad6dd43270fa632ac031e99d1947f20b22eec9
Create OCI config for linuxkit/dhcpcd:57a8ef29d3a910645b2b24c124f9ce9ef53ce703
Create OCI config for linuxkit/openntpd:a570316d7fc49ca1daa29bd945499f4963d227af
Create OCI config for redis:3.0.7-alpine
Add files:
etc/docker/daemon.json
Create outputs:
linux-redis-bzImage linux-redis-initrd.img linux-redis-cmdline

The following files are created:

  • The raw kernel image (linux-redis-bzImage)

  • The init ramdisk (linux-redis-initrd.img)

  • The commandline options youll need to provide to xhyve in a file

Operation and Output

Now the image is set up and ready to run.

First, you have to create a script that tells Xhyve how to mirror instances as virtual machines. Before that, it was emphasized that a Qcow image could be output through the Moby tool.

Then use Moby run to run Image just like VM. Xhyve is recommended because no other on-linuxkt operating system can run on the Hypervisor architecture.

Here's one thing you need to do to run the image: a copy of the Xhyve parameters defined to create the virtual machine. The main project in this script is captured from the Moby build process.

Here is an example of starting Redis server:

$ vi linux-redis.sh
#!/bin/sh

KERNEL="linux-redis-bzImage"
INITRD="linux-redis-initrd.img"
CMDLINE="console=ttyS0 console=tty0 page_poison=1"

MEM="-m 1G"
PCI_DEV="-s 0:0,hostbridge -s 31,lpc"
LPC_DEV="-l com1,stdio"
ACPI="-A"
#SMP="-c 2"

# sudo if you want networking enabled
NET="-s 2:0,virtio-net"

xhyve $ACPI $MEM $SMP $PCI_DEV $LPC_DEV $NET -f kexec,$KERNEL,$INITRD,"$CMDLINE"

Once the file has been created, make it executable and run it. There are some matters needing attention in the current link:

1. If any VPN is connected to the wireless network, please turn it off. Because there are some known traffic path problems when VPN runs.

2. If you are going to prepare a network connection to the virtual machine, you need to execute some superuser scripts.

Run it when it's okay:

$ chown 755 linux-redis.sh
$ sudo ./linux-redis.sh

When the virtual machine runs, there will be a set of Output Fly, and finally, on the new virtual machine, there will be a command line:

Welcome to LinuxKit

                       ##         .
                  ## ## ##        ==
               ## ## ## ## ##    ===
           /"""""""""""""""""\___/ ===
      ~~~ {~~ ~~~~ ~~~ ~~~~ ~~~ ~ /  ===- ~~~
           \______ o           __/
             \    \         __/
              \____\_______/

/ # [ 2.125127] IPVS: Creating netns size=2104 id=1
[ 2.125466] IPVS: ftp: loaded support on port[0] = 21
[ 2.156114] IPVS: Creating netns size=2104 id=2
[ 2.156496] IPVS: ftp: loaded support on port[0] = 21
[ 2.177714] tsc: Refined TSC clocksource calibration: 2193.340 MHz
[ 2.178170] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x1f9d9f9c94d, max_idle_ns: 440795310624 ns
[ 2.399509] IPVS: Creating netns size=2104 id=3
[ 2.400027] IPVS: ftp: loaded support on port[0] = 21
[ 2.670029] IPVS: Creating netns size=2104 id=4
[ 2.670555] IPVS: ftp: loaded support on port[0] = 21
[ 2.773492] random: dhcpcd: uninitialized urandom read (112 bytes read)
[ 2.791653] random: redis-server: uninitialized urandom read (19 bytes read)
[ 2.792066] random: redis-server: uninitialized urandom read (1024 bytes read)
[ 2.911251] IPVS: Creating netns size=2104 id=5
[ 2.911770] IPVS: ftp: loaded support on port[0] = 21
[ 2.935150] random: rngd: uninitialized urandom read (16 bytes read)
[ 2.955187] random: crng init done
[ 3.187797] clocksource: Switched to clocksource tsc

/ #

When Redis server is running, see what happens:

/ # netstat -an
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 0.0.0.0:6379 0.0.0.0:* LISTEN
tcp 0 0 :::6379 :::* LISTEN
udp 0 0 192.168.64.17:44773 52.6.160.3:123 ESTABLISHED
udp 0 0 192.168.64.17:44091 208.75.89.4:123 ESTABLISHED
udp 0 0 0.0.0.0:68 0.0.0.0:*
udp 0 0 192.168.64.17:33429 192.96.202.120:123 ESTABLISHED
udp 0 0 192.168.64.17:39584 69.89.207.99:123 ESTABLISHED
raw 0 0 ::%192:58 ::%32631:* 58
Active UNIX domain sockets (servers and established)
Proto RefCnt Flags Type State I-Node Path
unix 2 [ ACC ] STREAM LISTENING 14907 /var/run/dhcpcd.sock
unix 2 [ ACC ] STREAM LISTENING 14909 /var/run/dhcpcd.unpriv.sock
unix 2 [ ACC ] STREAM LISTENING 14248 /run/containerd/debug.sock
unix 2 [ ACC ] STREAM LISTENING 14258 /run/containerd/containerd.sock
unix 2 [ ACC ] STREAM LISTENING 15051 /var/run/ntpd.sock
unix 3 [ ] STREAM CONNECTED 15055
unix 3 [ ] STREAM CONNECTED 15050
unix 2 [ ] DGRAM 15025
unix 3 [ ] STREAM CONNECTED 15054
unix 3 [ ] STREAM CONNECTED 15049
/ #

It seems that the default port of EDIS for the machine is 6379. Now, see if it can be seen and accessed on the Internet. First, find the IP address of the virtual machine:

/ # ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: bond0: <BROADCAST,MULTICAST400> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether ca:41:0c:a4:ea:c2 brd ff:ff:ff:ff:ff:ff
3: dummy0: <BROADCAST,NOARP> mtu 1500 qdisc noop state DOWN qlen 1000
link/ether 1a:23:2d:47:af:d5 brd ff:ff:ff:ff:ff:ff
4: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether f2:94:56:b6:96:93 brd ff:ff:ff:ff:ff:ff
inet 192.168.64.17/24 brd 192.168.64.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::f094:56ff:feb6:9693/64 scope link
valid_lft forever preferred_lft forever
5: teql0: mtu 1500 qdisc noop state DOWN qlen 100
link/void
6: tunl0@NONE: mtu 1480 qdisc noop state DOWN qlen 1
link/ipip 0.0.0.0 brd 0.0.0.0
7: gre0@NONE: mtu 1476 qdisc noop state DOWN qlen 1
link/gre 0.0.0.0 brd 0.0.0.0
8: gretap0@NONE: <BROADCAST,MULTICAST> mtu 1462 qdisc noop state DOWN qlen 1000
link/ether 00:00:00:00:00:00 brd ff:ff:ff:ff:ff:ff
9: ip_vti0@NONE: mtu 1332 qdisc noop state DOWN qlen 1
link/ipip 0.0.0.0 brd 0.0.0.0
10: ip6_vti0@NONE: mtu 1500 qdisc noop state DOWN qlen 1
link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
11: sit0@NONE: mtu 1480 qdisc noop state DOWN qlen 1
link/sit 0.0.0.0 brd 0.0.0.0
12: ip6tnl0@NONE: mtu 1452 qdisc noop state DOWN qlen 1
link/tunnel6 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
13: ip6gre0@NONE: mtu 1448 qdisc noop state DOWN qlen 1
link/[823] 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 brd 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00

The ip address is 192.168.64.17. From the Max OS X host, Netcat is used to test the connection status and server status:

$ nc 192.168.64.17 6379
ping
+PONG

Once you have finished Poking around, type halt to close the virtual machine

/ # halt

Concluding remarks

Now we have an available Linux Kit image running in the OS X virtual machine.
However, this is just the beginning. You can use this template to create other images and customize what you want. At the same time, you don't have to use Redis to try to replace your own Docker images and start the virtual machine.

In subsequent articles, I will also try to use other Moby projece tools, such as Infrakit and Hyperkit, to demonstrate more capabilities of Linuxkt OS Images.

Links to the original text:
http://www.nebulaworks.com/bl...

Welcome your attention Several People Cloud Wechat Public Accounts If there are any follow-up articles, we will follow up as soon as possible.

Topics: Linux Redis Unix Docker