aetherscale

[unmaintained] code for a cloud provider tutorial
Log | Files | Refs | README | LICENSE

README.md (10083B)


      1 # aetherscale
      2 
      3 aetherscale is small hobby project to create a hosting environment that can
      4 be controlled with an API. I just want to have some fun and
      5 dive deeper into Linux tooling (networking, virtualization and so on) and
      6 into distributed applications. I do not think that this will become
      7 production-ready at any point.
      8 
      9 This is developed along with
     10 [a blog tutorial series about scalable computing](https://blog.stefan-koch.name/2020/11/22/programming-cloud-hosting-python-rabbitmq-qemu)
     11 which I am currently writing.
     12 
     13 ## Installation
     14 
     15 I recommend installation of the package in a virtual environment for
     16 easy removal and to avoid conflicts with system-wide packages:
     17 
     18 ```bash
     19 git clone https://github.com/aufziehvogel/aetherscale
     20 cd aetherscale
     21 virtualenv venv && source venv/bin/activate
     22 pip install .
     23 ```
     24 
     25 aetherscale must be able to adjust networking interfaces and routing. For
     26 more information on why it uses the following permission management, refer
     27 to the section *Rationale* below.
     28 
     29 To allow aetherscale to adjust networking and routing, give the user that
     30 is running aetherscale sudo permissions for the `ip` program, i.e. add the
     31 following line to your `visudo`:
     32 
     33 ```
     34 youruser ALL=(ALL) NOPASSWD: /usr/bin/ip, /usr/bin/radvd
     35 ```
     36 
     37 Currently, aetherscale also requires radvd for IPv6 in VPNs, but this will
     38 change in the future. We will expect users to handle their VPN completely
     39 on their own, i.e. there must be a DHCP or Router Advertisment server inside
     40 the VPN.
     41 
     42 
     43 ## Getting Started
     44 
     45 Each VM is booted from a base image, which has to be created in advance.
     46 To create a base image download an
     47 installation ISO for your favourite Linux distribution and install it to a
     48 qcow2 file with the following commands (and follow the installation
     49 instructions inside the started QEMU VM). When you're finished just shutdown
     50 the VM.
     51 
     52 ```bash
     53 BASE_IMAGE=base-image-name.qcow2
     54 ISO=your-distribution.iso
     55 
     56 qemu-img create -f qcow2 $BASE_IMAGE 20G
     57 qemu-system-x86_64 -cpu host -accel kvm -m 4096 -hda $BASE_IMAGE -cdrom $ISO
     58 ```
     59 
     60 The qcow2 base image must be located inside the
     61 `$BASE_IMAGE_FOLDER` directory. This is a configurable environment variable.
     62 
     63 aetherscale expects a bridge network `br0` on the physical ethernet which can
     64 be used to attach additional TAP interfaces for VMs. If this interface does not
     65 exist, an error will be displayed on startup of the server. Please refer to
     66 your network manager's documentation (e.g. ifupdown, systemd-networkd, ...)
     67 for instructions on how to create a bridge. For iproute2 I have [a short
     68 tutorial on my blog](https://blog.stefan-koch.name/2020/10/25/qemu-public-ip-vm-with-tap).
     69 
     70 To get started it's best to use the HTTP interface of the aetherscale
     71 server. While our HTTP implementation
     72 does not allow scaling to multiple machines it's a good way to play around
     73 with this program. You can start the HTTP server with:
     74 
     75 ```bash
     76 aetherscale http
     77 ```
     78 
     79 Once the server is running (on localhost port 5000 in this example) you can
     80 create a new VM from the previously created base image and list all
     81 VMs with:
     82 
     83 ```bash
     84 curl -XPOST -H "Content-Type: application/json" \
     85     -d '{"image": "ubuntu-20.04.1-server-amd64"}' http://localhost:5000/vm
     86 
     87 curl http://localhost:5000/vm
     88 ```
     89 
     90 The base image must be located at
     91 `$BASE_IMAGE_FOLDER/ubuntu-20.04.1-server-amd64.qcow2`.
     92 
     93 You can also stop a running VM and start a stopped VM by `PATCH`'ing the
     94 VM's REST endpoint with the desired status:
     95 
     96 ```bash
     97 curl -XPATCH -H "Content-Type: application/json" \
     98     -d '{"status": "stopped"}' http://localhost:5000/vm/adbvzwdf
     99 
    100 curl -XPATCH -H "Content-Type: application/json" \
    101     -d '{"status": "started"}' http://localhost:5000/vm/adbvzwdf
    102 ```
    103 
    104 Please note that stopping a VM (gracefully) takes some time, so you cannot
    105 start it immediately after you have issued a stop request.
    106 
    107 TODO: We might change this interface to
    108 [an `actions` endpoint](https://restful-api-design.readthedocs.io/en/latest/methods.html)
    109 and treat action requests as an ordered queue of requests.
    110 I.e., a stop request immediately followed by a start request should bring
    111 the VM down (which might take a few seconds) and afterwards start it again
    112 (even if the start request cam in before the VM was completely stopped).
    113 
    114 
    115 ## Run Tests
    116 
    117 You can run tests with `tox`:
    118 
    119 ```bash
    120 tox
    121 ```
    122 
    123 
    124 ## Overview
    125 
    126 Components which I think would be interesting to develop are:
    127 
    128 - Firewall (probably nftables, so that I can learn nftables)
    129 - Virtual Private Networks (probably tinc)
    130 - Virtual Servers (probably qemu)
    131   - IPv6-only intranet to learn IPv6
    132 
    133 ### Creating VMs
    134 
    135 When you want to create a new VM, you have to use a *base image*. This is an
    136 already prepared QEMU image in `qcow2` format that will be used to start your
    137 machine.
    138 
    139 You can define a custom script that is run on the first start of the machine.
    140 This can be used to install additional software or to configure software.
    141 The init-script is run by systemd and its output can be monitored with
    142 
    143 ```bash
    144 journalctl -f -u aetherscale-init
    145 ```
    146 
    147 Execution after the first boot of the machine is prohibited by a conditions
    148 file (cf. in `/etc/systemd/system/aetherscale-init.service`). If you
    149 want to run your script during another boot, you can delete the conditions
    150 file.
    151 
    152 ## Architecture
    153 
    154 My idea is that all requests to the system go through a central message
    155 broker. Handlers will then pick up these tasks and perform the work.
    156 
    157 Each request can have the name of a unique channel for responses. The sender
    158 of a message can open a channel with this name on the broker and will receive
    159 responses. This is useful if you have to wait until another component has
    160 performed their work.
    161 
    162 ### Files created by aetherscale
    163 
    164 aetherscale creates different files for VM management in your filesystem.
    165 My goal is to make aetherscale so simple that you can always fix or extend
    166 stuff manually. This section lists all relevant files that aetherscale creates.
    167 The aetherscale configuration directory is a config variable and thus might
    168 be changed. In this section it is refered to as `$CONFIG_DIR`, its default
    169 location is `~/.config/aetherscale`.
    170 
    171 For each VM aetherscale creates:
    172 
    173 - if required by the VM, networking setup scripts for the VM at
    174   `$CONFIG_DIR/networking/*-setup.sh` as well as teardown scripts at
    175   `$CONFIG_DIR/networking/*-teardown.sh`
    176 - a systemd user service file at
    177   `~/.config/systemd/user/aetherscale-vm-*.service`
    178 
    179 TODOs for VM networking:
    180 
    181 - TODO: Structure files into subfolders, e.g. `CONFIG/vm/vm-ID/IFACE-setup.sh`?
    182 
    183 For each VPN network aetherscale creates:
    184 
    185 - a tincd configuration folder structure at
    186   `$CONFIG_DIR/tinc` with one subfolder per VPN network
    187 - setup and teardown scripts for the host networking rules at
    188   `$CONFIG_DIR/networking/network-*-setup.sh` and
    189   `$CONFIG_DIR/networking/network-*-teardown.sh`
    190 - a systemd user service file at
    191   `~/.config/systemd/aetherscale-tincd-*.service`
    192 
    193 TODOs for VPN networking:
    194 
    195 - TODO: Rename prefix to `vpn` instead of `network`
    196 - TODO: Structure files into subfolders, e.g. `CONFIG/vpn/vpn-abc/setup.sh`?
    197 
    198 
    199 ### Computing
    200 
    201 Stuff I use for computing (and thus have learnt something about so far):
    202 
    203 - Qemu
    204 - software bridging with `ip` (for public and private IPs)
    205   - VDE could also be relevant, but currently out of scope
    206 - layer-2 VPN with tinc
    207 - `libguestfs` for analyzing and changing images
    208 - IPv6, radvd
    209 
    210 
    211 ## Rationale
    212 
    213 ### Operating System Changes
    214 
    215 I am trying to design aetherscale to run without root permissions for
    216 as much as possible.
    217 For some actions more permissions than a standard user usually has are
    218 needed, though. This section will guide you through all of the changes
    219 required to allow aetherscale itself to run as a standard user.
    220 
    221 #### Networking
    222 
    223 aetherscale has to adjust your networking in order to expose the VMs to the
    224 network. I decided to setup a bridge network for the VMs to join with
    225 `iproute2`.
    226 
    227 Bridge networks are used in two different situations:
    228 
    229 1. When exposing the VM to the public internet
    230 2. When establishing a VPN network between multiple VMs
    231 
    232 In both cases we use the `iproute2` (`ip`) utility. To allow aetherscale to
    233 run as a non-root user while still having access to networking changes, I
    234 decided to use `sudo` and allow rootless access to `ip`.
    235 
    236 For VPN there currently is one more change needed (but this is only
    237 temporary). To auto-configure IPv6 addresses of VPNs inside
    238 the guest VM we use IPv6 Router Advertisement messages. We run a `radvd`
    239 server that sends out the prefixes for IPv6 addresses. `radvd` also requires
    240 root permissions (to be exact it requires `CAP_NET_RAW` permissions).
    241 
    242 To allow these calls you have to enable passwordless sudo permissions with
    243 the following entry in `visudo`:
    244 
    245 ```
    246 youruser ALL=(ALL) NOPASSWD: /usr/bin/ip, /usr/bin/radvd
    247 ```
    248 
    249 Having `radvd` on the host machine is only a temporary solution. In a real
    250 setup, the VPN has to manage the internal IP addresses itself. We will
    251 probably provide an init-script template for a machine that does this.
    252 
    253 Requiring `sudo` is not a perfect solution but Linux capabilities inheritance to
    254 subprocesses seems quite complicated, and without inheritance we'd have to grant
    255 `CAP_NET_ADMIN` to both `ip` and `tincd`. This might be undesired, because
    256 then any user can change network devices. Another option could be to
    257 assign `CAP_NET_ADMIN` to the user running aetherscale, but this seems to
    258 [require changes to pam](https://unix.stackexchange.com/questions/454708/how-do-you-add-cap-sys-admin-permissions-to-user-in-centos-7)
    259 and still seems to require inheritable capabilities to be set on each
    260 binary that is to be executed.
    261 While this in my opinion would be a reasonable choice for a production
    262 program, it feels too heavy for a proof-of-concept tool.
    263 
    264 
    265 ## Contribution
    266 
    267 If you want to contribute you can:
    268 
    269 - create some steampunk artwork for this project :)
    270 - think about what else could be interesting to implement (especially if
    271   it runs as a daemon it should be based on well-established Linux technology
    272   that runs without babysitting it all day long)
    273 - create a routine for simple setup of the root installation steps