CloudStack Templates

From CSCWiki
Revision as of 19:54, 30 December 2021 by Merenber (talk | contribs) (Created page with "This page explains how to create CloudStack templates from which CloudStack VMs are based. Official documentation: https://docs.cloudstack.apache.org/en/latest/adminguide/tem...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search

This page explains how to create CloudStack templates from which CloudStack VMs are based.

Official documentation: https://docs.cloudstack.apache.org/en/latest/adminguide/templates.html

We require that cloud templates be prepared with cloud-init. cloud-init is a program which passes configuration data (e.g. user's SSH key) from a cloud provider to a VM at boot time. Most "major" GNU/Linux distributions have public cloud images which are (mostly) ready-to-use thanks to cloud-init.

Overview

There are two ways to create a template:

1. Convert the root disk volume of an existing VM into a template 2. Take a QCOW2 file, mount it over NBD, and modify files as necessary

The first option takes more time, but is generally easier. You can use either option; just keep in mind that some commands, such as systemctl, can only be executed in a live system.

Limitations

Downloading

If you are downloading a template over HTTP(S), there's one weird problem which I found out the hard way - the CloudStack Systems VMs' iptables rules are configured to block outgoing traffic to VLAN 134. I have no idea why CloudStack decides to do this, but you're going to have to work around those rules if you want to download a file hosted on a machine on-campus.

SSH into the Secondary Storage VM, e.g.

ssh -i /var/lib/cloudstack/management/.ssh/id_rsa -p 3922 root@169.254.12.1

Check if the first rule of the OUTPUT chain will accept all traffic:

iptables -L -vn

If not, add such a rule:

iptables -I OUTPUT 1 -j ACCEPT

Uploading

If you are uploading a QCOW2 image directly from your computer, you need to be on the campus network. For some reason the web UI tries to contact the management server directly, which of course has a private IP address. So either configure your browser to use a SOCKS proxy, or use the campus VPN.

Debian

We're going to start with Debian since it's the first template which I created. Other distributions are mostly similar.

From the CloudStack UI, as the admin user, click on Templates, then 'Register Template From URL'. Create a new template using this URL (change the release if necessary): https://cloud.debian.org/images/cloud/bullseye/latest/debian-11-genericcloud-amd64.qcow2. The following checkboxes should be checked: Extractable, HVM (don't make it public - we want members to use our modified templates instead).

Create a new VM using this template. Use the admin keypair during creation. Once it's ready, SSH into it using the admin keypair (on biloba or chamomile):

ssh -i /var/lib/cloudstack/management/.ssh/id_rsa debian@172.19.134.129

Replace the IP address as necessary.

IPv6 setup

We want the IPv6 address in our machines to be derived from the IPv4 address - for example, 172.19.134.129 becomes 2620:101:f000:4903::129. (Yes, I am aware that 129 in decimal is not the same as 129 in hex. But it makes it easier to remember.)

We're going to create some custom scripts which inject an IPv6 address at startup:

mkdir /etc/csc

# Here's a script to disable Router Advertisements (RA) and Duplicate Address Detection (DAD)
cat << 'EOF' > /etc/csc/ipv6-sysctl.sh
#!/bin/bash
set -ex
while read interface _; do    
        if [ $interface = lo ]; then
                continue
        fi
        sysctl net.ipv6.conf.$interface.accept_ra=0
        sysctl net.ipv6.conf.$interface.accept_dad=0
done < <(ip -brief link show)
EOF
chmod +x /etc/csc/ipv6-sysctl.sh

# Here's a script to derive the IPv6 address from the IPv4 address
cat << 'EOF' > /etc/csc/ipv6-addr.sh
#!/bin/bash
set -ex
INTERFACE=
IPV4_ADDRESS=
while read interface _ address; do
        if ! echo $address | grep -q '^172\.19\.134\.'; then
                continue
        fi
        INTERFACE=$interface
        IPV4_ADDRESS=$address
        break
done < <(ip -4 -brief addr show)
if [ -z "$INTERFACE" ]; then
        echo "Could not find primary interface" >&2
        exit 1
fi
NUM=$(echo $IPV4_ADDRESS | grep -oP '^172\.19\.134\.\K(\d+)')
IPV6_ADDRESS="2620:101:f000:4903::$NUM/64"
ip -6 addr add $IPV6_ADDRESS dev $INTERFACE
ip -6 route add default via 2620:101:f000:4903::1 dev $INTERFACE
EOF
chmod +x /etc/csc/ipv6-addr.sh

# Create some systemd services
cat <<EOF >/etc/systemd/system/csc-ipv6-sysctl.service
[Unit]
Description=Disable IPv6 RAs and DAD
# needed to avoid a dependency on basic.target
DefaultDependencies=no
After=network-pre.target
Before=networking.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/etc/csc/ipv6-sysctl.sh

[Install]
WantedBy=multi-user.target
EOF

cat <<EOF >/etc/systemd/system/csc-ipv6-addr.service
[Unit]
Description=Allocate IPv6 address
Requires=csc-ipv6-sysctl.service
After=csc-ipv6-sysctl.service
Requires=network.target
After=network.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/etc/csc/ipv6-addr.sh

[Install]
WantedBy=multi-user.target
EOF

# Enable the systemd services
systemctl daemon-reload
systemctl enable csc-ipv6-sysctl
systemctl enable csc-ipv6-addr