aboutsummaryrefslogtreecommitdiff
path: root/public/running-golang-application-as-pid1.html
diff options
context:
space:
mode:
Diffstat (limited to 'public/running-golang-application-as-pid1.html')
-rwxr-xr-xpublic/running-golang-application-as-pid1.html189
1 files changed, 189 insertions, 0 deletions
diff --git a/public/running-golang-application-as-pid1.html b/public/running-golang-application-as-pid1.html
new file mode 100755
index 0000000..3da57b0
--- /dev/null
+++ b/public/running-golang-application-as-pid1.html
@@ -0,0 +1,189 @@
1<!doctype html><html lang=en-us><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><link href="data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL69vf8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv76+/8LBwQkAAAAAAAAAAAAAAAC+vb3/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAL+9vf/Bv78JAAAAAAAAAAAAAAAAu7q6/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC7ubr/vr29CAAAAAAAAAAAy8nJAZ6foP8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAnqGj/6GipAoAAAAAHLjU/xcXHf/BwsL/I8XY/yPK3v8XGiD/IbjL/yPF2f8XGiD/Fxkf/yLF2f8gnK3/Fxog/62ztv8fwNf/FRcd/x271v8mz93/GRsi/xkXHf8p097/GiIp/xobIv8p0t3/KdPe/xocIv8fYmr/KNPe/xoZH/8aHCL/J87c/xy81/8VFxz/IsPZ/8zS0/8XGiD/Ir/R/yPH2/8XGiD/Fxkf/yPH2/8dd4T/GBog/yPJ3f8jyNr/uru9/xcUGv8cudb/EhITDKi5vRKlvMP/RUpOERwcHRAdOj4QHTk8EBwdHRAdNTgQHTo/EBwcHRAcHB0QSGduEKW4vf+koqQfHzg+EBqz0ewSFRv7EyMr/xq51vsTERb7ExUb+xq41fsau9j7ExUb+xiPp/sZudb7ExUb+xMVG/sZuNX/GKvI/BIUGfMdvdn/IrfL/xcaIP8n1eb/J9Dh/xkcIf8ZGR7/J8/f/xxCSv8ZGyH/J9Dg/ybQ4P8ZHCL/FSQs/yPK3/8UExj/GE1b/ybS5P8ZGB7/Ghwj/ynW5P8p2Ob/Ghwi/yWrtv8p1eH/Ghwi/xocIv8p1uT/J8XT/xkcIv8m1un/Hb7d/xUYH/8hzOr/HtHu/xcaIf8XGB//I8vi/xgxOv8XGSD/I8rg/yPK4P8XGiD/GUFL/yPP6f8SERj/Fhkh/x3A4f8AAAAAJ2f9/ydr//8mZPH/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlYu38J2v//ydo/f8AAAAAAAAAAAd8/fkFqf//Iob8sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMY39awWr//8FfP3/AAAAAAAAAAAFm/7/SfD//wR+/f8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOB/f9B7v//BaX+/wAAAAAAAAAAQ878SAyZ/v9n1v4KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADu9v8DDJb+/z3N/XgAAAAA3/sAAN/7AADf+wAA3/sAAAAAAAAAAAAAAAAAAN/7AAAAAAAAAAAAAAAAAAAAAAAAj/EAAI/5AACP8QAA3/sAAA==" rel=icon type=image/x-icon><title>Running Golang application as PID 1 with Linux kernel</title><meta name=description content="Unikernels, kernels, and alikeI have been reading a lot aboutunikernernels lately and found themvery intriguing."><link rel=alternate type=application/rss+xml title="Mitja Felicijan's posts" href=https://mitjafelicijan.com/index.xml><link rel=alternate type=application/rss+xml title="Mitja Felicijan's notes" href=https://mitjafelicijan.com/notes.xml><style>body{padding:1rem;max-width:760px;background:#fff;font-family:times new roman,Times,serif;line-height:1.35rem}hr{margin-block-start:1.5rem}h1,h2,h3{line-height:initial}footer{margin-block-start:3rem}table{max-width:100%;border-collapse:separate;border-spacing:2px;border:1px solid #000;border-left:1px solid #999;border-top:1px solid #999}blockquote{font-style:italic}table thead{background:#eee}td,th{border:1px solid #000;padding:4px;border-right:1px solid #999;border-bottom:1px solid #999;text-align:left}pre{text-wrap:nowrap;overflow-x:auto;margin-block-start:1.5rem;margin-block-end:1.5rem;padding:.5rem 0;border-top:1px solid #000;border-bottom:1px solid #000}pre code{line-height:1.3em}pre,code,pre *,code *{font-family:monospace;font-size:initial!important}img,video,audio{max-width:100%}header{display:flex;flex-direction:row;gap:3rem}nav{display:flex;gap:.75rem}.pstatus-orange{background:gold}.pstatus-green{background:#9acd32}.pstatus-red{background:#cd5c5c}@media only screen and (max-width:600px){header{flex-direction:column;gap:1rem}a{word-wrap:break-word}}</style><header><nav class=main><a href=/>Home</a>
2<a href=https://git.mitjafelicijan.com/ target=_blank>Git</a>
3<a href=https://files.mitjafelicijan.com/ target=_blank>Files</a>
4<a href=/mitjafelicijan.pgp.pub.txt target=_blank>PGP</a>
5<a href=/curriculum-vitae.html>CV</a>
6<a href=/index.xml target=_blank>RSS</a></nav></header><main><div><h1>Running Golang application as PID 1 with Linux kernel</h1><p>Dec 25, 2021<div><h2 id=unikernels-kernels-and-alike>Unikernels, kernels, and alike</h2><p>I have been reading a lot about
7<a href=https://en.wikipedia.org/wiki/Unikernel>unikernernels</a> lately and found them
8very intriguing. When you push away all the marketing speak and look at the
9idea, it makes a lot of sense.<blockquote><p>A unikernel is a specialized, single address space machine image constructed
10by using library operating systems. (<a href=https://en.wikipedia.org/wiki/Unikernel>Wikipedia</a>)</blockquote><p>I really like the explanation from the article
11<a href="https://queue.acm.org/detail.cfm?id=2566628">Unikernels: Rise of the Virtual Library Operating System</a>.
12Really worth a read.<p>If we compare a normal operating system to a unikernel side by side, they would
13look something like this.<p><img src=/assets/pid1/unikernels.png alt="Virtual machines vs Containers vs Unikernels"><p>From this image, we can see how the complexity significantly decreases with
14the use of Unikernels. This comes with a price, of course. Unikernels are hard
15to get running and require a lot of work since you don't have an actual proper
16kernel running in the background providing network access and drivers etc.<p>So as a half step to make the stack simpler, I started looking into using
17Linux kernel as a base and going from there. I came across this
18<a href="https://www.youtube.com/watch?v=Sk9TatW9ino">Youtube video talking about Building the Simplest Possible Linux System</a>
19by <a href=https://landley.net>Rob Landley</a> and apart from statically compiling the
20application to be run as PID1 there was really no other obstacles.<h2 id=what-is-pid-1>What is PID 1?</h2><p>PID 1 is the first process that Linux kernel starts after the boot process.
21It also has a couple of unique properties that are unique to it.<ul><li>When the process with PID 1 dies for any reason, all other processes are
22killed with KILL signal.<li>When any process having children dies for any reason, its children are
23re-parented to process with PID 1.<li>Many signals which have default action of Term do not have one for PID 1.<li>When the process with PID 1 dies for any reason, kernel panics, which
24result in system crash.</ul><p>PID 1 is considered as an Init application which takes care of running other
25and handling services like:<ul><li>sshd,<li>nginx,<li>pulseaudio,<li>etc.</ul><p>If you are on a Linux machine, you can check what your process is with PID 1
26by running the following.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ cat /proc/1/status
27</span></span><span style=display:flex><span>Name: systemd
28</span></span><span style=display:flex><span>Umask: 0000
29</span></span><span style=display:flex><span>State: S (sleeping)
30</span></span><span style=display:flex><span>Tgid: 1
31</span></span><span style=display:flex><span>Ngid: 0
32</span></span><span style=display:flex><span>Pid: 1
33</span></span><span style=display:flex><span>PPid: 0
34</span></span><span style=display:flex><span>...
35</span></span></code></pre><p>As we can see on my machine the process with id of 1 is <a href=https://systemd.io/>systemd</a>
36which is a software suite that provides an array of system components for Linux
37operating systems. If you look closely you can also see that the <code>PPid</code>
38(process id of the parent process) is <code>0</code> which additionally confirms that
39this process doesn't have a parent.<h2 id=so-why-even-run-application-as-pid-1-instead-of-just-using-a-container>So why even run application as PID 1 instead of just using a container?</h2><p>Containers are wonderful, but they come with a lot of baggage. And because they
40are in their nature layered, the images require quite a lot of space and also a
41lot of additional software to handle them. They are not as lightweight as they
42seem, and many popular images require 500 MB plus disk space.<p>The idea of running this as PID 1 would result in a significantly smaller footprint,
43as we will see later in the post.<blockquote><p>You could run a simple init system inside Docker container described more
44in this article <a href=https://blog.phusion.nl/2015/01/20/docker-and-the-pid-1-zombie-reaping-problem/>Docker and the PID 1 zombie reaping problem</a>.</blockquote><h2 id=the-master-plan>The master plan</h2><ol><li>Compile Linux kernel with the default definitions.<li>Prepare a Hello World application in Golang that is statically compiled.<li>Run it with <a href=https://www.qemu.org/>QEMU</a> and providing Golang application
45as init application / PID 1.</ol><p>For the sake of simplicity we will not be cross-compiling any of it and just
46use the 64bit version.<h2 id=compiling-linux-kernel>Compiling Linux kernel</h2><pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.7.tar.xz
47</span></span><span style=display:flex><span>$ tar xf linux-5.15.7.tar.xz
48</span></span><span style=display:flex><span>
49</span></span><span style=display:flex><span>$ cd linux-5.15.7
50</span></span><span style=display:flex><span>
51</span></span><span style=display:flex><span>$ make clean
52</span></span><span style=display:flex><span>
53</span></span><span style=display:flex><span><span style=color:green># read more about this https://stackoverflow.com/a/41886394</span>
54</span></span><span style=display:flex><span>$ make defconfig
55</span></span><span style=display:flex><span>
56</span></span><span style=display:flex><span>$ time make -j <span style=color:#a31515>`</span>nproc<span style=color:#a31515>`</span>
57</span></span><span style=display:flex><span>
58</span></span><span style=display:flex><span>$ cd ..
59</span></span></code></pre><p>At this point we have kernel image that is located in <code>arch/x86_64/boot/bzImage</code>.
60We will use this in QEMU later.<p>To make our lives a bit easier lets move the kernel image to another place.
61Lets create a folder <code>bin/</code> in the root of our project with <code>mkdir -p bin</code>.<p>At this point we can copy <code>bzImage</code> to <code>bin/</code> folder with
62<code>cp linux-5.15.7/arch/x86_64/boot/bzImage bin/bzImage</code>.<p>The folder structure of this experiment should look like this.<pre><code>pid1/
63 bin/
64 bzImage
65 linux-5.15.7/
66 linux-5.15.7.tar.xz
67</code></pre><h2 id=preparing-pid-1-application-in-golang>Preparing PID 1 application in Golang</h2><p>This step is relatively easy. The only thing we must have in mind that we will
68need to compile the binary as a static one.<p>Let's create <code>init.go</code> file in the root of the project.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span><span style=color:#00f>package</span> main
69</span></span><span style=display:flex><span>
70</span></span><span style=display:flex><span><span style=color:#00f>import</span> (
71</span></span><span style=display:flex><span> <span style=color:#a31515>&#34;fmt&#34;</span>
72</span></span><span style=display:flex><span> <span style=color:#a31515>&#34;time&#34;</span>
73</span></span><span style=display:flex><span>)
74</span></span><span style=display:flex><span>
75</span></span><span style=display:flex><span><span style=color:#00f>func</span> main() {
76</span></span><span style=display:flex><span> <span style=color:#00f>for</span> {
77</span></span><span style=display:flex><span> fmt.Println(<span style=color:#a31515>&#34;Hello from Golang&#34;</span>)
78</span></span><span style=display:flex><span> time.Sleep(1 * time.Second)
79</span></span><span style=display:flex><span> }
80</span></span><span style=display:flex><span>}
81</span></span></code></pre><p>If you notice, we have a forever loop in the main, with a simple sleep of 1
82second to not overwhelm the CPU. This is because PID 1 should never complete
83and/or exit. That would result in a kernel panic. Which is BAD!<p>There are two ways of compiling Golang application. Statically and dynamically.<p>To statically compile the binary, use the following command.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ go build -ldflags=<span style=color:#a31515>&#34;-extldflags=-static&#34;</span> init.go
84</span></span></code></pre><p>We can also check if the binary is statically compiled with:<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ file init
85</span></span><span style=display:flex><span>init: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), statically linked, Go BuildID=Ypu8Zw_4NBxm1Yxg2OYO/H5x721rQ9uTPiDVh-VqP/vZN7kXfGG1zhX_qdHMgH/9vBfmK81tFrygfOXDEOo, not stripped
86</span></span><span style=display:flex><span>
87</span></span><span style=display:flex><span>$ ldd init
88</span></span><span style=display:flex><span>not a dynamic executable
89</span></span></code></pre><p>At this point, we need to create <a href=https://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html>initramfs</a>
90(abbreviated from "initial RAM file system", is the successor of initrd. It
91is a cpio archive of the initial file system that gets loaded into memory
92during the Linux startup process).<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ echo init | cpio -o --format=newc &gt; initramfs
93</span></span><span style=display:flex><span>$ mv initramfs bin/initramfs
94</span></span></code></pre><p>The projects at this stage should look like this.<pre><code>pid1/
95 bin/
96 bzImage
97 initramfs
98 linux-5.15.7/
99 linux-5.15.7.tar.xz
100 init.go
101</code></pre><h2 id=running-all-of-it-with-qemu>Running all of it with QEMU</h2><p><a href=https://www.qemu.org/>QEMU</a> is a free and open-source hypervisor. It emulates
102the machine's processor through dynamic binary translation and provides a set
103of different hardware and device models for the machine, enabling it to run a
104variety of guest operating systems.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ qemu-system-x86_64 -serial stdio -kernel bin/bzImage -initrd bin/initramfs -append <span style=color:#a31515>&#34;console=ttyS0&#34;</span> -m 128
105</span></span></code></pre><pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ qemu-system-x86_64 -serial stdio -kernel bin/bzImage -initrd bin/initramfs -append <span style=color:#a31515>&#34;console=ttyS0&#34;</span> -m 128
106</span></span><span style=display:flex><span>[ 0.000000] Linux version 5.15.7 (m@khan) (gcc (GCC) 11.2.1 20211203 (Red Hat 11.2.1-7), GNU ld version 2.37-10.fc35) <span style=color:green>#7 SMP Mon Dec 13 10:23:25 CET 2021</span>
107</span></span><span style=display:flex><span>[ 0.000000] Command line: console=ttyS0
108</span></span><span style=display:flex><span>[ 0.000000] x86/fpu: x87 FPU will use FXSAVE
109</span></span><span style=display:flex><span>[ 0.000000] signal: max sigframe size: 1440
110</span></span><span style=display:flex><span>[ 0.000000] BIOS-provided physical RAM map:
111</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
112</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
113</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
114</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x0000000000100000-0x0000000007fdffff] usable
115</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x0000000007fe0000-0x0000000007ffffff] reserved
116</span></span><span style=display:flex><span>[ 0.000000] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
117</span></span><span style=display:flex><span>[ 0.000000] NX (Execute Disable) protection: active
118</span></span><span style=display:flex><span>[ 0.000000] SMBIOS 2.8 present.
119</span></span><span style=display:flex><span>[ 0.000000] DMI: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-6.fc35 04/01/2014
120</span></span><span style=display:flex><span>[ 0.000000] tsc: Fast TSC calibration failed
121</span></span><span style=display:flex><span>...
122</span></span><span style=display:flex><span>[ 2.016106] ALSA device list:
123</span></span><span style=display:flex><span>[ 2.016329] No soundcards found.
124</span></span><span style=display:flex><span>[ 2.053176] Freeing unused kernel image (initmem) memory: 1368K
125</span></span><span style=display:flex><span>[ 2.056095] Write protecting the kernel read-only data: 20480k
126</span></span><span style=display:flex><span>[ 2.058248] Freeing unused kernel image (text/rodata gap) memory: 2032K
127</span></span><span style=display:flex><span>[ 2.058811] Freeing unused kernel image (rodata/data gap) memory: 500K
128</span></span><span style=display:flex><span>[ 2.059164] Run /init as init process
129</span></span><span style=display:flex><span>Hello from Golang
130</span></span><span style=display:flex><span>[ 2.386879] tsc: Refined TSC clocksource calibration: 3192.032 MHz
131</span></span><span style=display:flex><span>[ 2.387114] clocksource: tsc: mask: 0xffffffffffffffff max_cycles: 0x2e02e31fa14, max_idle_ns: 440795264947 ns
132</span></span><span style=display:flex><span>[ 2.387380] clocksource: Switched to clocksource tsc
133</span></span><span style=display:flex><span>[ 2.587895] input: ImExPS/2 Generic Explorer Mouse as /devices/platform/i8042/serio1/input/input3
134</span></span><span style=display:flex><span>Hello from Golang
135</span></span><span style=display:flex><span>Hello from Golang
136</span></span><span style=display:flex><span>Hello from Golang
137</span></span></code></pre><p>The whole <a href=/assets/pid1/qemu.log>log file here</a>.<h2 id=size-comparison>Size comparison</h2><p>The cool thing about this approach is that the Linux kernel and the application
138together only take around 12 MB, which is impressive as hell. And we need to
139also know that the size of bzImage (Linux kernel) could be greatly decreased
140by going into <code>make menuconfig</code> and removing a ton of features from the kernel,
141making the size even smaller. I managed to get kernel size down to 2 MB and
142still working properly.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>total 12M
143</span></span><span style=display:flex><span>-rw-r--r--. 1 m m 9.3M Dec 13 10:24 bzImage
144</span></span><span style=display:flex><span>-rw-r--r--. 1 m m 1.9M Dec 27 01:19 initramfs
145</span></span></code></pre><h2 id=creating-iso-image-and-running-it-with-gnome-boxes>Creating ISO image and running it with Gnome Boxes</h2><p>First we need to create proper folder structure with <code>mkdir -p iso/boot/grub</code>.<p>Then we need to download the <a href=https://github.com/littleosbook/littleosbook/raw/master/files/stage2_eltorito>grub binary</a>.
146You can read more about this program on <a href=https://github.com/littleosbook/littleosbook>https://github.com/littleosbook/littleosbook</a>.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ wget -O iso/boot/grub/stage2_eltorito https://github.com/littleosbook/littleosbook/raw/master/files/stage2_eltorito
147</span></span></code></pre><pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ tree iso/boot/
148</span></span><span style=display:flex><span>iso/boot/
149</span></span><span style=display:flex><span>├── bzImage
150</span></span><span style=display:flex><span>├── grub
151</span></span><span style=display:flex><span>│   ├── menu.lst
152</span></span><span style=display:flex><span>│   └── stage2_eltorito
153</span></span><span style=display:flex><span>└── initramfs
154</span></span></code></pre><p>Let's copy files into proper folders.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>$ cp stage2_eltorito iso/boot/grub/
155</span></span><span style=display:flex><span>$ cp bin/bzImage iso/boot/
156</span></span><span style=display:flex><span>$ cp bin/initramfs iso/boot/
157</span></span></code></pre><p>Lets create a GRUB config file at <code>nano iso/boot/grub/menu.lst</code> with contents.<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>default=<span style=color:#a31515>0</span>
158</span></span><span style=display:flex><span>timeout=<span style=color:#a31515>5</span>
159</span></span><span style=display:flex><span>
160</span></span><span style=display:flex><span>title GoAsPID1
161</span></span><span style=display:flex><span>kernel /boot/bzImage
162</span></span><span style=display:flex><span>initrd /boot/initramfs
163</span></span></code></pre><p>Let's create iso file by using genisoimage:<pre tabindex=0 style=background-color:#fff><code><span style=display:flex><span>genisoimage -R <span style=color:#a31515>\
164</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -b boot/grub/stage2_eltorito <span style=color:#a31515>\
165</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -no-emul-boot <span style=color:#a31515>\
166</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -boot-load-size 4 <span style=color:#a31515>\
167</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -A os <span style=color:#a31515>\
168</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -input-charset utf8 <span style=color:#a31515>\
169</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -quiet <span style=color:#a31515>\
170</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -boot-info-table <span style=color:#a31515>\
171</span></span></span><span style=display:flex><span><span style=color:#a31515></span> -o GoAsPID1.iso <span style=color:#a31515>\
172</span></span></span><span style=display:flex><span><span style=color:#a31515></span> iso
173</span></span></code></pre><p>This will produce <code>GoAsPID1.iso</code> which you can use with <a href=https://www.virtualbox.org/>Virtualbox</a>
174or <a href=https://apps.gnome.org/app/org.gnome.Boxes/>Gnome Boxes</a>.<p><video src=/assets/pid1/boxes.mp4 controls></video><h2 id=is-running-applications-as-pid-1-even-worth-it>Is running applications as PID 1 even worth it?</h2><p>Well, the answer to this is not as simple as one would think. Sometimes it is
175and sometimes it's not. For embedded systems and very specialized applications
176it is worth for sure. But in normal uses, I don't think so. It was an interesting
177exercise in compiling kernels and looking at the guts of the Linux kernel,
178but sticking to containers for most of the things is a better option in my
179opinion.<p>An interesting experiment would be creating an image that supports networking
180and could be deployed to AWS as an EC2 instance and observing how it fares.
181But in that case, we would need to write some sort of supervisor that would
182run on a separate EC2 that would check if other EC2 instances are running
183properly. Remember that if your application fails, kernel panics and the
184whole machine is inoperable in this case.</div></div></main><footer><hr><div><h3>Want to comment or have something to add?</h3>You can write me an email at
185<a href=mailto:m@mitjafelicijan.com>m@mitjafelicijan.com</a> or catch up
186with me
187<a href=https://telegram.me/mitjafelicijan target=_blank>on Telegram</a>.</div><hr><p>This website does not track you. Content is made available under
188the <a href=https://creativecommons.org/licenses/by/4.0/ target=_blank rel=noreferrer>CC BY 4.0 license</a> unless specified
189otherwise. Blog feed is available as <a href=/index.xml target=_blank>RSS feed</a>.</footer><script src=https://cdn.usefathom.com/script.js data-site=XHQARKXP defer></script> \ No newline at end of file