This repository has been archived by the owner on Mar 4, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Makefile, configuration files and scripts
Update the README with instructions on setting up, configuring, building and running the Nginx app with Unikraft. As part of it, add Makefile files, configuration files and scripts; they are referenced in the `README.md` file. Current instructions cover the use of QEMU/KVM platform (both on x86_64 and on AArch64) and GCC. Firecraker/KVM, Xen, Linux platforms and Clang are not yet documented. Signed-off-by: Razvan Deaconescu <razvand@unikraft.io> Reviewed-by: Stefan Jumarea <stefanjumarea02@gmail.com> Approved-by: Stefan Jumarea <stefanjumarea02@gmail.com> Tested-by: Unikraft CI <monkey@unikraft.io> GitHub-Closes: #13
- Loading branch information
1 parent
dfab6b2
commit d69f1ab
Showing
7 changed files
with
1,257 additions
and
62 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
UK_ROOT ?= $(PWD)/.unikraft/unikraft | ||
UK_LIBS ?= $(PWD)/.unikraft/libs | ||
LIBS := $(UK_LIBS)/musl:$(UK_LIBS)/lwip:$(UK_LIBS)/nginx | ||
|
||
all: | ||
@$(MAKE) -C $(UK_ROOT) A=$(PWD) L=$(LIBS) | ||
|
||
$(MAKECMDGOALS): | ||
@$(MAKE) -C $(UK_ROOT) A=$(PWD) L=$(LIBS) $(MAKECMDGOALS) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
$(eval $(call addlib,appnginx)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,93 +1,325 @@ | ||
# Nginx on Unikraft | ||
|
||
This application starts an NginX web server. | ||
This application starts an Nginx web server with Unikraft. | ||
Follow the instructions below to set up, configure, build and run Nginx. | ||
|
||
To configure, build and run the application you need to have [kraft](https://github.com/unikraft/kraft) installed. | ||
## Requirements | ||
|
||
To be able to interact with the web server, configure the application to run on the KVM platform: | ||
``` | ||
$ kraft configure -p kvm -m x86_64 | ||
``` | ||
In order to set up, configure, build and run Nginx on Unikraft, the following packages are required: | ||
|
||
Build the application: | ||
``` | ||
$ kraft build | ||
``` | ||
* `build-essential` / `base-devel` / `@development-tools` (the meta-package that includes `make`, `gcc` and other development-related packages) | ||
* `sudo` | ||
* `flex` | ||
* `bison` | ||
* `git` | ||
* `wget` | ||
* `uuid-runtime` | ||
* `qemu-system-x86` | ||
* `qemu-system-arm` | ||
* `qemu-kvm` | ||
* `sgabios` | ||
* `gcc-aarch64-linux-gnu` | ||
|
||
GCC >= 8 is required to build Nginx on Unikraft. | ||
|
||
We use a virtual bridge to create a connection between the VM and the host system. | ||
We assign address `172.44.0.1/24` to the bridge interface (pointing to the host) and we assign address `172.44.0.2/24` to the virtual machine, by passing boot arguments. | ||
The IP addresses are of our choosing, they can be changed to other values. | ||
On Ubuntu/Debian or other `apt`-based distributions, run the following command to install the requirements: | ||
|
||
We run the commands below to create and assign the IP address to the bridge `virbr0` (once again, our choice of name; any name works): | ||
```console | ||
$ apt-get install -y --no-install-recommends \ | ||
build-essential \ | ||
sudo \ | ||
gcc-aarch64-linux-gnu \ | ||
libncurses-dev \ | ||
libyaml-dev \ | ||
flex \ | ||
bison \ | ||
git \ | ||
wget \ | ||
uuid-runtime \ | ||
qemu-kvm \ | ||
qemu-system-x86 \ | ||
qemu-system-arm \ | ||
sgabios | ||
``` | ||
$ sudo brctl addbr virbr0 | ||
$ sudo ip a a 172.44.0.1/24 dev virbr0 | ||
$ sudo ip l set dev virbr0 up | ||
|
||
Running Nginx Unikraft with QEMU requires networking support. | ||
For this to work properly a specific configuration must be enabled for QEMU. | ||
Run the commands below to enable that configuration (for the network bridge to work): | ||
|
||
```console | ||
$ sudo mkdir /etc/qemu/ | ||
$ echo "allow all" | sudo tee /etc/qemu/bridge.conf | ||
``` | ||
|
||
We can check the proper configuration: | ||
## Set Up | ||
|
||
The following repositories are required for Nginx: | ||
|
||
* The application repository (this repository): [`app-nginx`](https://github.com/unikraft/app-nginx) | ||
* The Unikraft core repository: [`unikraft`](https://github.com/unikraft/unikraft) | ||
* Library repositories: | ||
* The Nginx "library" repository: [`lib-nginx`](https://github.com/unikraft/lib-nginx) | ||
* The standard C library: [`lib-musl`](https://github.com/unikraft/lib-musl) | ||
* The networking stack library: [`lib-lwip`](https://github.com/unikraft/lib-lwip) | ||
|
||
Follow the steps below for the setup: | ||
|
||
1. First clone the [`app-nginx` repository](https://github.com/unikraft/app-nginx) in the `nginx/` directory: | ||
|
||
```console | ||
$ git clone https://github.com/unikraft/app-nginx nginx | ||
``` | ||
|
||
Enter the `nginx/` directory: | ||
|
||
```console | ||
$ cd nginx/ | ||
|
||
$ ls -F | ||
config-qemu-aarch64 config-qemu-x86_64 fs0/ kraft.yaml Makefile Makefile.uk README.md run-qemu-aarch64.sh* run-qemu-x86_64.sh* | ||
``` | ||
|
||
1. While inside the `nginx/` directory, create the `.unikraft/` directory: | ||
|
||
```console | ||
$ mkdir .unikraft | ||
``` | ||
|
||
Enter the `.unikraft/` directory: | ||
|
||
```console | ||
$ cd .unikraft/ | ||
``` | ||
|
||
1. While inside the `.unikraft` directory, clone the [`unikraft` repository](https://github.com/unikraft/unikraft): | ||
|
||
```console | ||
$ git clone https://github.com/unikraft/unikraft unikraft | ||
``` | ||
|
||
1. While inside the `.unikraft/` directory, create the `libs/` directory: | ||
|
||
```console | ||
$ mkdir libs | ||
``` | ||
|
||
1. While inside the `.unikraft/` directory, clone the library repositories in the `libs/` directory: | ||
|
||
```console | ||
$ git clone https://github.com/unikraft/lib-nginx libs/nginx | ||
|
||
$ git clone https://github.com/unikraft/lib-musl libs/musl | ||
|
||
$ git clone https://github.com/unikraft/lib-lwip libs/lwip | ||
``` | ||
|
||
1. Get back to the application directory: | ||
|
||
```console | ||
$ cd ../ | ||
``` | ||
|
||
Use the `tree` command to inspect the contents of the `.unikraft/` directory. | ||
It should print something like this: | ||
|
||
```console | ||
$ tree -F -L 2 .unikraft/ | ||
.unikraft/ | ||
|-- libs/ | ||
| |-- lwip/ | ||
| |-- musl/ | ||
| `-- nginx/ | ||
`-- unikraft/ | ||
|-- arch/ | ||
|-- Config.uk | ||
|-- CONTRIBUTING.md | ||
|-- COPYING.md | ||
|-- include/ | ||
|-- lib/ | ||
|-- Makefile | ||
|-- Makefile.uk | ||
|-- plat/ | ||
|-- README.md | ||
|-- support/ | ||
`-- version.mk | ||
|
||
10 directories, 7 files | ||
``` | ||
|
||
## Configure | ||
|
||
Configuring, building and running a Unikraft application depends on our choice of platform and architecture. | ||
Currently, supported platforms are QEMU (KVM), Xen and linuxu. | ||
QEMU (KVM) is known to be working, so we focus on that. | ||
|
||
Supported architectures are x86_64 and AArch64. | ||
|
||
Use the corresponding the configuration files (`config-...`), according to your choice of platform and architecture. | ||
|
||
### QEMU x86_64 | ||
|
||
Use the `config-qemu-x86_64` configuration file together with `make defconfig` to create the configuration file: | ||
|
||
```console | ||
$ UK_DEFCONFIG=$(pwd)/config-qemu-x86_64 make defconfig | ||
``` | ||
$ ip a s virbr0 | ||
420: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default qlen 1000 | ||
link/ether 3a:3e:88:e6:a1:e4 brd ff:ff:ff:ff:ff:ff | ||
inet 172.44.0.1/24 scope global virbr0 | ||
valid_lft forever preferred_lft forever | ||
inet6 fe80::383e:88ff:fee6:a1e4/64 scope link | ||
valid_lft forever preferred_lft forever | ||
|
||
This results in the creation of the `.config` file: | ||
|
||
```console | ||
$ ls .config | ||
.config | ||
``` | ||
|
||
Now we start the virtual machine and pass it the proper arguments to assing the IP address `172.44.0.2/24`: | ||
The `.config` file will be used in the build step. | ||
|
||
### QEMU AArch64 | ||
|
||
Use the `config-qemu-aarch64` configuration file together with `make defconfig` to create the configuration file: | ||
|
||
```console | ||
$ UK_DEFCONFIG=$(pwd)/config-qemu-aarch64 make defconfig | ||
``` | ||
$ kraft run -b virbr0 "netdev.ipv4_addr=172.44.0.2 netdev.ipv4_gw_addr=172.44.0.1 netdev.ipv4_subnet_mask=255.255.255.0 --" | ||
|
||
Similar to the x86_64 configuration, this results in the creation of the `.config` file that will be used in the build step. | ||
|
||
## Build | ||
|
||
Building uses as input the `.config` file from above, and results in a unikernel image as output. | ||
The unikernel output image, together with intermediary build files, are stored in the `build/` directory. | ||
|
||
### Clean Up | ||
|
||
Before starting a build on a different platform or architecture, you must clean up the build output. | ||
This may also be required in case of a new configuration. | ||
|
||
Cleaning up is done with 3 possible commands: | ||
|
||
* `make clean`: cleans all actual build output files (binary files, including the unikernel image) | ||
* `make properclean`: removes the entire `build/` directory | ||
* `make distclean`: removes the entire `build/` directory **and** the `.config` file | ||
|
||
Typically, you would use `make properclean` to remove all build artifacts, but keep the configuration file. | ||
|
||
### QEMU x86_64 | ||
|
||
Building for QEMU x86_64 assumes you did the QEMU x86_64 configuration step above. | ||
Build the Unikraft Nginx image for QEMU x86_64 by using the command below: | ||
|
||
```console | ||
$ make -j $(nproc) | ||
[...] | ||
0: Set IPv4 address 172.44.0.2 mask 255.255.255.0 gw 172.44.0.1 | ||
en0: Added | ||
en0: Interface is up | ||
LD nginx_qemu-x86_64.dbg | ||
UKBI nginx_qemu-x86_64.dbg.bootinfo | ||
SCSTRIP nginx_qemu-x86_64 | ||
GZ nginx_qemu-x86_64.gz | ||
make[1]: Leaving directory '/media/razvan/c4f6765a-efa5-4ebd-9cf0-7da9908a0189/razvan/unikraft/solo/nginx/.unikraft/unikraft' | ||
``` | ||
|
||
At the end of the build command, the `nginx_qemu-x86_64` unikernel image is generated. | ||
This image is to be used in the run step. | ||
|
||
### QEMU AArch64 | ||
|
||
If you had configured and build a unikernel image for another platform or architecture (such as x86_64) before, then: | ||
|
||
1. Do a cleanup step with `make properclean`. | ||
|
||
1. Configure for QEMU AAarch64, as shown above. | ||
|
||
1. Follow the instructions below to build for QEMU AArch64. | ||
|
||
Building for QEMU AArch64 assumes you did the QEMU AArch64 configuration step above. | ||
Build the Unikraft Nginx image for QEMU AArch64 by using the same command as for x86_64: | ||
|
||
```console | ||
$ make -j $(nproc) | ||
[...] | ||
LD nginx_qemu-arm64.dbg | ||
UKBI nginx_qemu-arm64.dbg.bootinfo | ||
SCSTRIP nginx_qemu-arm64 | ||
GZ nginx_qemu-arm64.gz | ||
make[1]: Leaving directory '/media/razvan/c4f6765a-efa5-4ebd-9cf0-7da9908a0189/razvan/unikraft/solo/nginx/.unikraft/unikraft | ||
``` | ||
|
||
The boot message confirms the assigning of the `172.44.0.2/24` IP address to the virtual machine. | ||
We use `wget` to validate it's working properly and we are able to get the `index.html` file: | ||
Similarly to x86_64, at the end of the build command, the `nginx_qemu-arm64` unikernel image is generated. | ||
This image is to be used in the run step. | ||
|
||
## Run | ||
|
||
Run the resulting image with the `run-...` scripts. | ||
|
||
### QEMU x86_64 | ||
|
||
To run the QEMU x86_64 build, use `run-qemu-x86_64.sh`: | ||
|
||
```console | ||
$ ./run-qemu-x86_64.sh | ||
qemu-system-x86_64: warning: TCG doesn't support requested feature: CPUID.01H:ECX.vmx [bit 5] | ||
1: Set IPv4 address 172.44.0.2 mask 255.255.255.0 gw 172.44.0.1 | ||
en1: Added | ||
en1: Interface is up | ||
Powered by | ||
o. .o _ _ __ _ | ||
Oo Oo ___ (_) | __ __ __ _ ' _) :_ | ||
oO oO ' _ `| | |/ / _)' _` | |_| _) | ||
oOo oOO| | | | | (| | | (_) | _) :_ | ||
OoOoO ._, ._:_:_,\_._, .__,_:_, \___) | ||
Atlas 0.13.1~5eb820bd | ||
``` | ||
|
||
The server listens for connections on the `172.44.0.2` address advertised. | ||
A web client (such as `wget`) is required to query the server. | ||
|
||
Open another console and use the `wget` command below to query the server: | ||
|
||
```console | ||
$ wget 172.44.0.2 | ||
--2021-08-18 16:47:38-- http://172.44.0.2/ | ||
--2023-07-01 13:53:24-- http://172.44.0.2/ | ||
Connecting to 172.44.0.2:80... connected. | ||
HTTP request sent, awaiting response... 200 OK | ||
[...] | ||
2021-08-18 16:47:38 (41.5 MB/s) - ‘index.html’ saved [160] | ||
``` | ||
Length: 180 [text/html] | ||
Saving to: ‘index.html’ | ||
|
||
Cleaning up means closing the virtual machine (and the HTTP server) and disabling and deleting the bridge interface: | ||
``` | ||
$ sudo ip l set dev virbr0 down | ||
$ sudo brctl delbr virbr0 | ||
index.html 100%[================================================================================================>] 180 --.-KB/s in 0s | ||
|
||
2023-07-01 13:53:25 (12.6 MB/s) - ‘index.html’ saved [180/180] | ||
``` | ||
|
||
If you want to have more control you can also configure, build and run the application manually. | ||
To close the QEMU Nginx server, use the `Ctrl+a x` keyboard shortcut; | ||
that is press the `Ctrl` and `a` keys at the same time and then, separately, press the `x` key. | ||
|
||
To configure it for the KVM platform: | ||
``` | ||
$ make menuconfig | ||
``` | ||
### QEMU AArch64 | ||
|
||
Build the application: | ||
``` | ||
$ make | ||
``` | ||
To run the AArch64 build, use `run-qemu-aarch64.sh`: | ||
|
||
Run the application: | ||
``` | ||
sudo qemu-system-x86_64 -fsdev local,id=myid,path=$(pwd)/fs0,security_model=none \ | ||
-device virtio-9p-pci,fsdev=myid,mount_tag=fs0,disable-modern=on,disable-legacy=off \ | ||
-netdev bridge,id=en0,br=virbr0 \ | ||
-device virtio-net-pci,netdev=en0 \ | ||
-kernel "build/app-nginx_kvm-x86_64" \ | ||
-append "netdev.ipv4_addr=172.44.0.2 netdev.ipv4_gw_addr=172.44.0.1 netdev.ipv4_subnet_mask=255.255.255.0 --" \ | ||
-cpu host \ | ||
-enable-kvm \ | ||
-nographic | ||
```console | ||
$ ./run-qemu-aarch64.sh | ||
1: Set IPv4 address 172.44.0.2 mask 255.255.255.0 gw 172.44.0.1 | ||
en1: Added | ||
en1: Interface is up | ||
Powered by | ||
o. .o _ _ __ _ | ||
Oo Oo ___ (_) | __ __ __ _ ' _) :_ | ||
oO oO ' _ `| | |/ / _)' _` | |_| _) | ||
oOo oOO| | | | | (| | | (_) | _) :_ | ||
OoOoO ._, ._:_:_,\_._, .__,_:_, \___) | ||
Atlas 0.13.1~5eb820bd | ||
``` | ||
|
||
Open another console and use the `wget` command, similar to the QEMU x86_64 run above: | ||
|
||
```console | ||
$ wget 172.44.0.2 | ||
--2023-07-01 14:32:26-- http://172.44.0.2/ | ||
Connecting to 172.44.0.2:80... connected. | ||
HTTP request sent, awaiting response... 200 OK | ||
Length: 180 [text/html] | ||
Saving to: ‘index.html’ | ||
|
||
index.html 100%[================================================================================================>] 180 --.-KB/s in 0s | ||
|
||
2023-07-01 14:32:26 (9.87 MB/s) - ‘index.html’ saved [180/180] | ||
``` | ||
|
||
For more information about `kraft` type ```kraft -h``` or read the | ||
[documentation](http://docs.unikraft.org). | ||
Similarly, to close the QEMU Nginx server, use the `Ctrl+a x` keyboard shortcut. |
Oops, something went wrong.