diff options
| author | Mitja Felicijan <mitja.felicijan@gmail.com> | 2021-12-27 08:33:15 +0100 |
|---|---|---|
| committer | Mitja Felicijan <mitja.felicijan@gmail.com> | 2021-12-27 08:33:15 +0100 |
| commit | 5d03373461b0dbb928835f2cc14d95893916ad99 (patch) | |
| tree | 3c0e9b016c6ed8f406610c53c010dda241f0fb6c /posts/2021-12-25-running-golang-application-as-pid1.md | |
| parent | a66d22924c1001c4298e0c290aa2e40c5c418f1e (diff) | |
| download | mitjafelicijan.com-5d03373461b0dbb928835f2cc14d95893916ad99.tar.gz | |
Added new content to PID1
Diffstat (limited to 'posts/2021-12-25-running-golang-application-as-pid1.md')
| -rw-r--r-- | posts/2021-12-25-running-golang-application-as-pid1.md | 84 |
1 files changed, 72 insertions, 12 deletions
diff --git a/posts/2021-12-25-running-golang-application-as-pid1.md b/posts/2021-12-25-running-golang-application-as-pid1.md index c211c8b..a3dc078 100644 --- a/posts/2021-12-25-running-golang-application-as-pid1.md +++ b/posts/2021-12-25-running-golang-application-as-pid1.md | |||
| @@ -15,7 +15,8 @@ Tags: [] | |||
| 15 | 6. [Preparing PID 1 application in Golang](#preparing-pid-1-application-in-golang) | 15 | 6. [Preparing PID 1 application in Golang](#preparing-pid-1-application-in-golang) |
| 16 | 7. [Running all of it with QEMU](#running-all-of-it-with-qemu) | 16 | 7. [Running all of it with QEMU](#running-all-of-it-with-qemu) |
| 17 | 8. [Size comparison](#size-comparison) | 17 | 8. [Size comparison](#size-comparison) |
| 18 | 9. [Is running applications as PID 1 even worth it?](#is-running-applications-as-pid-1-even-worth-it) | 18 | 9. [Creating ISO image and running with VirtualBox](#creating-iso-image-and-running-with-virtualbox) |
| 19 | 10. [Is running applications as PID 1 even worth it?](#is-running-applications-as-pid-1-even-worth-it) | ||
| 19 | 20 | ||
| 20 | ## Unikernels, kernels, and alike | 21 | ## Unikernels, kernels, and alike |
| 21 | 22 | ||
| @@ -84,19 +85,19 @@ For the sake of simplicity we will not be cross-compiling any of it and just use | |||
| 84 | ## Compiling Linux kernel | 85 | ## Compiling Linux kernel |
| 85 | 86 | ||
| 86 | ```sh | 87 | ```sh |
| 87 | wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.7.tar.xz | 88 | $ wget https://cdn.kernel.org/pub/linux/kernel/v5.x/linux-5.15.7.tar.xz |
| 88 | tar xf linux-5.15.7.tar.xz | 89 | $ tar xf linux-5.15.7.tar.xz |
| 89 | 90 | ||
| 90 | cd linux-5.15.7 | 91 | $ cd linux-5.15.7 |
| 91 | 92 | ||
| 92 | make clean | 93 | $ make clean |
| 93 | 94 | ||
| 94 | # read more about this https://stackoverflow.com/a/41886394 | 95 | # read more about this https://stackoverflow.com/a/41886394 |
| 95 | make defconfig | 96 | $ make defconfig |
| 96 | 97 | ||
| 97 | time make -j `nproc` | 98 | $ time make -j `nproc` |
| 98 | 99 | ||
| 99 | cd .. | 100 | $ cd .. |
| 100 | ``` | 101 | ``` |
| 101 | 102 | ||
| 102 | At this point we have kernel image that is located in `arch/x86_64/boot/bzImage`. We will use this in QEMU later. | 103 | At this point we have kernel image that is located in `arch/x86_64/boot/bzImage`. We will use this in QEMU later. |
| @@ -145,7 +146,7 @@ There are two ways of compiling Golang application. Statically and dynamically. | |||
| 145 | To statically compile the binary, use the following command. | 146 | To statically compile the binary, use the following command. |
| 146 | 147 | ||
| 147 | ```sh | 148 | ```sh |
| 148 | go build -ldflags="-extldflags=-static" init.go | 149 | $ go build -ldflags="-extldflags=-static" init.go |
| 149 | ``` | 150 | ``` |
| 150 | 151 | ||
| 151 | We can also check if the binary is statically compiled with: | 152 | We can also check if the binary is statically compiled with: |
| @@ -161,8 +162,8 @@ not a dynamic executable | |||
| 161 | At this point, we need to create [initramfs](https://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html) (abbreviated from "initial RAM file system", is the successor of initrd. It is a cpio archive of the initial file system that gets loaded into memory during the Linux startup process). | 162 | At this point, we need to create [initramfs](https://www.linuxfromscratch.org/blfs/view/svn/postlfs/initramfs.html) (abbreviated from "initial RAM file system", is the successor of initrd. It is a cpio archive of the initial file system that gets loaded into memory during the Linux startup process). |
| 162 | 163 | ||
| 163 | ```sh | 164 | ```sh |
| 164 | echo init | cpio -o --format=newc > initramfs | 165 | $ echo init | cpio -o --format=newc > initramfs |
| 165 | mv initramfs bin/initramfs | 166 | $ mv initramfs bin/initramfs |
| 166 | ``` | 167 | ``` |
| 167 | 168 | ||
| 168 | The projects at this stage should look like this. | 169 | The projects at this stage should look like this. |
| @@ -182,7 +183,7 @@ pid1/ | |||
| 182 | [QEMU](https://www.qemu.org/) is a free and open-source hypervisor. It emulates the machine's processor through dynamic binary translation and provides a set of different hardware and device models for the machine, enabling it to run a variety of guest operating systems. | 183 | [QEMU](https://www.qemu.org/) is a free and open-source hypervisor. It emulates the machine's processor through dynamic binary translation and provides a set of different hardware and device models for the machine, enabling it to run a variety of guest operating systems. |
| 183 | 184 | ||
| 184 | ```sh | 185 | ```sh |
| 185 | qemu-system-x86_64 -serial stdio -kernel bin/bzImage -initrd bin/initramfs -append "console=ttyS0" -m 128 | 186 | $ qemu-system-x86_64 -serial stdio -kernel bin/bzImage -initrd bin/initramfs -append "console=ttyS0" -m 128 |
| 186 | ``` | 187 | ``` |
| 187 | 188 | ||
| 188 | ```sh | 189 | ```sh |
| @@ -232,6 +233,65 @@ total 12M | |||
| 232 | -rw-r--r--. 1 m m 1.9M Dec 27 01:19 initramfs | 233 | -rw-r--r--. 1 m m 1.9M Dec 27 01:19 initramfs |
| 233 | ``` | 234 | ``` |
| 234 | 235 | ||
| 236 | ## Creating ISO image and running with VirtualBox | ||
| 237 | |||
| 238 | First we need to create proper folder structure with `mkdir -p iso/boot/grub`. | ||
| 239 | |||
| 240 | Then we need to download the [grub binary](https://github.com/littleosbook/littleosbook/raw/master/files/stage2_eltorito). You can read more about this program on https://github.com/littleosbook/littleosbook. | ||
| 241 | |||
| 242 | ```sh | ||
| 243 | $ wget -O iso/boot/grub/stage2_eltorito https://github.com/littleosbook/littleosbook/raw/master/files/stage2_eltorito | ||
| 244 | ``` | ||
| 245 | |||
| 246 | ```sh | ||
| 247 | $ tree iso/boot/ | ||
| 248 | iso/boot/ | ||
| 249 | ├── bzImage | ||
| 250 | ├── grub | ||
| 251 | │ ├── menu.lst | ||
| 252 | │ └── stage2_eltorito | ||
| 253 | └── initramfs | ||
| 254 | ``` | ||
| 255 | |||
| 256 | Let's copy files into proper folders. | ||
| 257 | |||
| 258 | |||
| 259 | ```sh | ||
| 260 | $ cp stage2_eltorito iso/boot/grub/ | ||
| 261 | $ cp bin/bzImage iso/boot/ | ||
| 262 | $ cp bin/initramfs iso/boot/ | ||
| 263 | ``` | ||
| 264 | |||
| 265 | Lets create a GRUB config file at `nano iso/boot/grub/menu.lst` with contents. | ||
| 266 | |||
| 267 | ```ini | ||
| 268 | default=0 | ||
| 269 | timeout=5 | ||
| 270 | |||
| 271 | title GoAsPID1 | ||
| 272 | kernel /boot/bzImage | ||
| 273 | initrd /boot/initramfs | ||
| 274 | ``` | ||
| 275 | |||
| 276 | Let's create iso file by using genisoimage: | ||
| 277 | |||
| 278 | ```sh | ||
| 279 | genisoimage -R \ | ||
| 280 | -b boot/grub/stage2_eltorito \ | ||
| 281 | -no-emul-boot \ | ||
| 282 | -boot-load-size 4 \ | ||
| 283 | -A os \ | ||
| 284 | -input-charset utf8 \ | ||
| 285 | -quiet \ | ||
| 286 | -boot-info-table \ | ||
| 287 | -o GoAsPID1.iso \ | ||
| 288 | iso | ||
| 289 | ``` | ||
| 290 | |||
| 291 | This will produce `GoAsPID1.iso` which you can use with [Virtualbox](https://www.virtualbox.org/) or [Gnome Boxes](https://apps.gnome.org/app/org.gnome.Boxes/). | ||
| 292 | |||
| 293 | <video src="/assets/pid1/boxes.mp4" controls></video> | ||
| 294 | |||
| 235 | ## Is running applications as PID 1 even worth it? | 295 | ## Is running applications as PID 1 even worth it? |
| 236 | 296 | ||
| 237 | Well, the answer to this is not as simple as one would think. Sometimes it is and sometimes it's not. For embedded systems and very specialized applications it is worth for sure. But in normal uses, I don't think so. It was an interesting exercise in compiling kernels and looking at the guts of the Linux kernel, but sticking to containers for most of the things is a better option in my opinion. | 297 | Well, the answer to this is not as simple as one would think. Sometimes it is and sometimes it's not. For embedded systems and very specialized applications it is worth for sure. But in normal uses, I don't think so. It was an interesting exercise in compiling kernels and looking at the guts of the Linux kernel, but sticking to containers for most of the things is a better option in my opinion. |
