Skip to content

Commit 5e7718d

Browse files
committed
Add support for Canonical MaaS Provider
1 parent f7dae54 commit 5e7718d

36 files changed

+1441
-1
lines changed

docs/book/src/SUMMARY.md

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
- [vSphere](./capi/providers/vsphere.md)
2020
- [Proxmox](./capi/providers/proxmox.md)
2121
- [Windows](./capi/windows/windows.md)
22+
- [MaaS](./capi/providers/maas.md)
2223
- [Including ECR Credential Provider](./capi/ecr-credential-provider.md)
2324
- [Testing the Images](./capi/goss/goss.md)
2425
- [Using Container Images](./capi/container-image.md)

docs/book/src/capi/capi.md

+1
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ If any needed binaries are not present, they can be installed to `images/capi/.b
3030
* [VirtualBox](./providers/virtualbox.md)
3131
* [vSphere](./providers/vsphere.md)
3232
* [Proxmox](./providers/proxmox.md)
33+
* [MaaS](./providers/maas.md)
3334

3435
## Make targets
3536

docs/book/src/capi/providers/maas.md

+76
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
# Building Images for MaaS
2+
3+
The image is built using the KVM hypervisor (QEMU).
4+
5+
## Building Images
6+
7+
The build [prerequisites](../capi.md#prerequisites) for using `image-builder` to create QEMU images are installed with:
8+
9+
```bash
10+
cd image-builder
11+
make deps-qemu
12+
```
13+
14+
## Building a MaaS Image
15+
16+
From the `image-builder` directory, run:
17+
18+
```bash
19+
make build-maas-ubuntu-xxxx-efi
20+
```
21+
22+
The image will be located in `images/capi/output/BUILD_NAME+kube-KUBERNETES_VERSION`. Replace `xxxx` with `2204` or `2404`, depending on the Ubuntu version.
23+
24+
To build a Ubuntu 22.04-based CAPI image:
25+
26+
```bash
27+
git clone https://github.com/kubernetes-sigs/image-builder.git
28+
cd image-builder
29+
make build-qemu-ubuntu-2204-efi
30+
```
31+
32+
## Uploading to MaaS
33+
34+
### Prerequisites
35+
36+
- Ubuntu 22.04 (required for the MaaS client)
37+
- Command-line MaaS client installed
38+
39+
### Installing the MaaS Client
40+
41+
```bash
42+
apt update && apt install -y tzdata software-properties-common
43+
apt-add-repository -y ppa:maas/3.5
44+
apt install -y maas-cli python3-openssl
45+
```
46+
47+
### Logging into MaaS
48+
49+
```bash
50+
maas login admin <MAAS_HTTP_ENDPOINT>/MAAS/ '<TOKEN>'
51+
```
52+
53+
#### Creating a Token
54+
55+
Log into the MaaS interface, go to your preferences (your username), click "API Keys," and copy an existing key or generate a new one.
56+
57+
### Uploading the Image
58+
59+
Navigate to `images/capi/output/`, find the generated image, and enter its directory. Inside, you will see two files:
60+
61+
```bash
62+
cd images/capi/output/ubuntu-2204-efi-kube-v1.30.5/
63+
64+
ls -l
65+
total 7165084
66+
-rw-r--r-- 1 vasartori vasartori 5132255232 Feb 25 08:33 ubuntu-2204-efi-kube-v1.30.5
67+
-rw-r--r-- 1 root root 2203701699 Feb 25 08:33 ubuntu-2204-efi-kube-v1.30.5.tar.gz
68+
```
69+
70+
Use the **.tar.gz** file for the upload:
71+
72+
```bash
73+
maas admin boot-resources create name=custom/your-image architecture=amd64/generic title=your-image subarches=generic base_image=ubuntu/jammy content@=./ubuntu-2204-efi-kube-v1.30.5.tar.gz
74+
```
75+
76+
**Note:** Set `base_image=ubuntu/jammy` for Ubuntu 22.04 or `ubuntu/noble` for 24.04.

docs/book/src/glossary.md

+11-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Table of Contents
22

3-
[A](#a) | [C](#c) | [E](#e) | [G](#g) | [K](#k) | [O](#o) | [V](#v)
3+
[A](#a) | [C](#c) | [E](#e) | [G](#g) | [K](#k) | [M](#m) | [O](#o) | [V](#v)
44

55
# A
66
---
@@ -76,6 +76,16 @@ Kubernetes (K8s) is an open-source system for automating deployment, scaling, an
7676
[source](https://github.com/kubernetes/kubernetes)
7777
[docs](https://kubernetes.io)
7878

79+
# M
80+
---
81+
82+
## MaaS
83+
84+
Metal As A Service (a.k.a MaaS) is an open-source tool developed by Canonical that automates the provisioning and management of bare-metal servers.
85+
86+
[docs](https://maas.io/docs)
87+
88+
7989
# O
8090
---
8191

images/capi/Makefile

+16
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,8 @@ PROXMOX_BUILD_NAMES ?= proxmox-ubuntu-2204 proxmox-ubuntu-2404 proxmox-ubuntu-
400400

401401
VULTR_BUILD_NAMES ?= vultr-ubuntu-2204
402402

403+
MAAS_BUILD_NAMES ?= maas-ubuntu-2204-efi maas-ubuntu-2404-efi
404+
403405
## --------------------------------------
404406
## Dynamic build targets
405407
## --------------------------------------
@@ -448,6 +450,8 @@ PROXMOX_BUILD_TARGETS := $(addprefix build-,$(PROXMOX_BUILD_NAMES))
448450
PROXMOX_VALIDATE_TARGETS := $(addprefix validate-,$(PROXMOX_BUILD_NAMES))
449451
VULTR_BUILD_TARGETS := $(addprefix build-,$(VULTR_BUILD_NAMES))
450452
VULTR_VALIDATE_TARGETS := $(addprefix validate-,$(VULTR_BUILD_NAMES))
453+
MAAS_BUILD_TARGETS := $(addprefix build-,$(MAAS_BUILD_NAMES))
454+
MAAS_VALIDATE_TARGETS := $(addprefix validate-,$(MAAS_BUILD_NAMES))
451455

452456
.PHONY: $(NODE_OVA_LOCAL_BUILD_TARGETS)
453457
$(NODE_OVA_LOCAL_BUILD_TARGETS): deps-ova set-ssh-password
@@ -640,6 +644,15 @@ $(VULTR_BUILD_TARGETS): deps-vultr
640644
$(VULTR_VALIDATE_TARGETS): deps-vultr
641645
$(PACKER) validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/vultr/$(subst validate-vultr-,,$@).json)" $(ABSOLUTE_PACKER_VAR_FILES) packer/vultr/packer.json
642646

647+
.PHONY: $(MAAS_BUILD_TARGETS)
648+
$(MAAS_BUILD_TARGETS): deps-qemu set-ssh-password
649+
$(PACKER) build $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/maas/$(subst build-,,$@).json)" --var="ansible_user_vars=provider=maas" $(ABSOLUTE_PACKER_VAR_FILES) packer/maas/packer.json
650+
651+
.PHONY: $(MAAS_VALIDATE_TARGETS)
652+
$(MAAS_VALIDATE_TARGETS): deps-qemu set-ssh-password
653+
$(PACKER) validate $(PACKER_NODE_FLAGS) -var-file="$(abspath packer/maas/$(subst validate-,,$@).json)" --var="ansible_user_vars=provider=maas" $(ABSOLUTE_PACKER_VAR_FILES) packer/maas/packer.json
654+
655+
643656
## --------------------------------------
644657
## Dynamic clean targets
645658
## --------------------------------------
@@ -847,6 +860,9 @@ build-qemu-rockylinux-9: ## Builds Rocky 9 QEMU image
847860
build-qemu-rockylinux-9-cloudimg: ## Builds Rocky 9 QEMU image using cloud image
848861
build-qemu-all: $(QEMU_BUILD_TARGETS) ## Builds all Qemu images
849862

863+
build-maas-ubuntu-2204-efi: ## Builds Ubuntu 22.04 MaaS image that EFI boots
864+
build-maas-ubuntu-2404-efi: ## Builds Ubuntu 24.04 MaaS image that EFI boots
865+
850866
build-raw-flatcar: ## Builds Flatcar RAW image
851867
build-raw-ubuntu-2004: ## Builds Ubuntu 20.04 RAW image
852868
build-raw-ubuntu-2004-efi: ## Builds Ubuntu 20.04 RAW image that EFI boots
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Attribution
2+
All the script in this folder is derived from the original work by Alexsander de Souza (Canonical),
3+
available at https://github.com/canonical/packer-maas.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#!/usr/bin/env python3
2+
#
3+
# This script was copied as-is from:
4+
# Source: https://github.com/canonical/packer-maas
5+
# Original Author: Alexsander de Souza <[email protected]>
6+
#
7+
8+
9+
import os
10+
import platform
11+
import shutil
12+
import sys
13+
14+
from curtin import distro, util
15+
from curtin.commands import apt_config, curthooks
16+
from curtin.config import load_command_config
17+
from curtin.log import DEBUG, LOG, basicConfig
18+
from curtin.paths import target_path
19+
from curtin.util import ChrootableTarget, load_command_environment
20+
21+
22+
def run_hook_in_target(target, hook):
23+
"""Look for "hook" in "target" and run in a chroot"""
24+
target_hook = target_path(target, "/curtin/" + hook)
25+
if os.path.isfile(target_hook):
26+
LOG.debug("running %s" % target_hook)
27+
with ChrootableTarget(target=target) as in_chroot:
28+
in_chroot.subp(["/curtin/" + hook])
29+
return True
30+
return False
31+
32+
33+
def curthook(cfg, target, state):
34+
"""Configure network and bootloader"""
35+
LOG.info("Running curtin builtin curthooks")
36+
state_etcd = os.path.split(state["fstab"])[0]
37+
machine = platform.machine()
38+
39+
distro_info = distro.get_distroinfo(target=target)
40+
if not distro_info:
41+
raise RuntimeError("Failed to determine target distro")
42+
osfamily = distro_info.family
43+
LOG.info(
44+
"Configuring target system for distro: %s osfamily: %s",
45+
distro_info.variant,
46+
osfamily,
47+
)
48+
49+
sources = cfg.get("sources", {})
50+
dd_image = len(util.get_dd_images(sources)) > 0
51+
52+
curthooks.disable_overlayroot(cfg, target)
53+
curthooks.disable_update_initramfs(cfg, target, machine)
54+
curthooks.install_missing_packages(cfg, target, osfamily=osfamily)
55+
56+
if not dd_image:
57+
curthooks.configure_iscsi(cfg, state_etcd, target, osfamily=osfamily)
58+
curthooks.configure_mdadm(cfg, state_etcd, target, osfamily=osfamily)
59+
curthooks.copy_fstab(state.get("fstab"), target)
60+
curthooks.add_swap(cfg, target, state.get("fstab"))
61+
62+
run_hook_in_target(target, "install-custom-packages")
63+
64+
if not dd_image:
65+
curthooks.setup_kernel_img_conf(target)
66+
67+
crypttab_location = os.path.join(os.path.split(state["fstab"])[0], "crypttab")
68+
if os.path.exists(crypttab_location):
69+
curthooks.copy_crypttab(crypttab_location, target)
70+
71+
udev_rules_d = os.path.join(state["scratch"], "rules.d")
72+
if os.path.isdir(udev_rules_d):
73+
curthooks.copy_dname_rules(udev_rules_d, target)
74+
75+
apt_config.apply_debconf_selections(cfg, target)
76+
77+
curthooks.apply_networking(target, state)
78+
curthooks.handle_pollinate_user_agent(cfg, target)
79+
80+
# re-enable update_initramfs
81+
curthooks.enable_update_initramfs(cfg, target, machine)
82+
curthooks.update_initramfs(target, all_kernels=True)
83+
84+
run_hook_in_target(target, "setup-bootloader")
85+
86+
87+
def cleanup():
88+
"""Remove curtin-hooks so its as if we were never here."""
89+
curtin_dir = os.path.dirname(__file__)
90+
shutil.rmtree(curtin_dir)
91+
92+
93+
def main():
94+
state = load_command_environment()
95+
config = load_command_config(None, state)
96+
target = state["target"]
97+
98+
basicConfig(stream=sys.stderr, verbosity=DEBUG)
99+
100+
curthook(config, target, state)
101+
cleanup()
102+
103+
104+
if __name__ == "__main__":
105+
main()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/bash -ex
2+
#
3+
exit 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#!/bin/bash -ex
2+
#
3+
# This script was copied as-is from:
4+
# Source: https://github.com/canonical/packer-maas
5+
# Original Author: Alexsander de Souza <[email protected]>
6+
7+
export DEBIAN_FRONTEND=noninteractive
8+
9+
# Clean up remnants from packer-maas vm install
10+
rm /var/cache/debconf/config.dat
11+
dpkg --configure -a
12+
13+
# Update the package lists before attempting to install the kernel
14+
apt-get update
15+
# Ensure the existence of linux-image-generic for non-cloudimg images.
16+
apt-get -y install linux-image-generic
17+
18+
dpkg-reconfigure grub-efi-amd64
19+
update-grub
20+
21+
grub-install \
22+
--target=x86_64-efi \
23+
--efi-directory=/boot/efi \
24+
--bootloader-id=ubuntu \
25+
--recheck
26+
27+
update-initramfs -uk all
28+
29+
efibootmgr -v
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
- name: Create /curtin directory
2+
ansible.builtin.file:
3+
path: /curtin
4+
state: directory
5+
mode: "0775"
6+
7+
- name: Copy curtin scripts to /curtin
8+
ansible.builtin.copy:
9+
src: "files/maas/curtin/{{ item }}"
10+
dest: "/curtin/{{ item }}"
11+
mode: "0750"
12+
loop:
13+
- curtin-hooks
14+
- install-custom-packages
15+
- setup-bootloader
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
- ansible.builtin.include_tasks: qemu.yml
2+
3+
- ansible.builtin.include_tasks: maas-ubuntu.yml
4+
when: ansible_os_family == "Debian"

images/capi/ansible/roles/providers/tasks/main.yml

+3
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@
5454
- ansible.builtin.include_tasks: huaweicloud.yml
5555
when: packer_builder_type.startswith('huaweicloud')
5656

57+
- ansible.builtin.include_tasks: maas.yml
58+
when: packer_builder_type is search('qemu') and provider is defined and provider is search('maas')
59+
5760
# Create a boot order configuration
5861
# b/w containerd and cloud final, cloud config services
5962

images/capi/packer/maas/.gitignore

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
packer.json
2+
ks.cfg
3+
preseed.cfg
4+
preseed-efi.cfg
5+
user-data

images/capi/packer/maas/OWNERS

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# See the OWNERS docs at https://go.k8s.io/owners
2+
3+
approvers:
4+
- cluster-api-openstack-maintainers
5+
- cluster-api-cloudstack-maintainers
6+
7+
reviewers:
8+
- cluster-api-openstack-maintainers
9+
- image-builder-openstack-reviewers
10+
- cluster-api-cloudstack-maintainers
11+
- image-builder-cloudstack-reviewers

images/capi/packer/maas/README.md

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
To build an image using a specific version of Kubernetes use the "PACKER_FLAGS" env var like in the example below:
2+
3+
PACKER_FLAGS="--var 'kubernetes_rpm_version=1.30.5' --var 'kubernetes_semver=v1.30.5' --var 'kubernetes_series=v1.30' --var 'kubernetes_deb_version=1.30.5-1.1'" make build-maas-ubuntu-2204-efi
4+
5+
P.S: In order to change disk size(defaults to 20GB as of 31.10.22) you can update PACKER_FLAGS with:
6+
--var 'disk_size=<disk size in mb>'
7+
8+
9+
Upload images to MaaS
10+
11+
```
12+
maas <PROFILE> boot-resources create name=custom/<IMAGE NAME> architecture=amd64/generic title=<IMAGE NAME> subarches=generic base_image=ubuntu/<SEE NOTES> content@=./<FILE>.tar.gz
13+
```
14+
15+
Notes / Things you need to known:
16+
17+
- If you are using ubuntu **22.04**, set the `base_image` field to: `ubuntu/jammy`. For 24.04, use: `ubuntu/noble`
18+
- Use **UEFI** to boot the machines, if you use BIOS, your MaaS deployment will **probably** fail.

images/capi/packer/maas/cloud-init/meta-data

Whitespace-only changes.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
#cloud-config
2+
ssh_pwauth: true
3+
users:
4+
- name: builder
5+
passwd: $ENCRYPTED_SSH_PASSWORD
6+
groups: [adm, cdrom, dip, plugdev, lxd, sudo]
7+
lock-passwd: false
8+
sudo: ALL=(ALL) NOPASSWD:ALL
9+
shell: /bin/bash
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
packer {
2+
required_plugins {
3+
qemu = {
4+
source = "github.com/hashicorp/qemu"
5+
version = "~> 1.1.0"
6+
}
7+
}
8+
}

images/capi/packer/maas/linux/ubuntu/http/22.04.efi.qemu/meta-data

Whitespace-only changes.

0 commit comments

Comments
 (0)