Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 99 additions & 0 deletions deploy/ansible/playbooks/pb-pxe-controller.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

---
- name: Setup PXE Controller for diskless k3s agent boot
hosts: pxe_controller
become: true
gather_facts: true
vars:
# ── config.env equivalent ──────────────────────────────
pxe_rootfs_force_rebuild: false
# Network -- REQUIRED: fill in for your environment. Left empty on purpose;
# the role asserts each of these is set and fails fast if any is empty.
# pxe_network_interface: service-machine NIC that serves PXE (e.g. "enp1s0")
# pxe_subnet: node subnet in CIDR form (e.g. "192.168.1.0/24")
# pxe_gateway: default gateway for the node subnet (informational)
# pxe_dns_servers: comma-separated DNS servers for the rootfs
pxe_network_interface: ""
pxe_subnet: ""
pxe_gateway: ""
pxe_dns_servers: ""

# PXE Controller -- REQUIRED: set to your service host IP. Left empty;
# the role fails fast if it is not set.
pxe_controller_ip: ""

# k3s Server Nodes -- REQUIRED: set to your k3s server node IP(s). Left
# empty; the role fails fast if the list is empty. If you have multiple k3s
# server nodes, add each one to the list, e.g.
# pxe_k3s_server_ips:
# - "<K3S_SERVER_IP_1>"
# - "<K3S_SERVER_IP_2>"
pxe_k3s_server_ips: []

# k3s version baked into the agent rootfs. Keep this in sync with the k3s
# server (k3s_version in deploy/ansible/inventory.yml). Agents must be the
# same version as, or older than, the server.
pxe_k3s_version: "v1.32.3+k3s1"

# Root password for PXE-booted machines (leave empty to disable password login)
# Use ansible-vault: ansible-vault encrypt_string 'MyPass' --name 'pxe_rootfs_password'
pxe_rootfs_password: ""

# SSH keys for rootfs login (at least one required -- fill in before running).
# The playbook fails fast if this list is empty.
pxe_rootfs_authorized_keys: []
# - "ssh-ed25519 AAAA... you@workstation"
# - "ssh-rsa AAAA... ci@runner"

# APT Mirror
pxe_apt_mirror: "http://tw.archive.ubuntu.com/ubuntu"

pxe_rootfs_packages:
- linux-image-6.14.0-1018-oem
- linux-headers-6.14.0-1018-oem
- initramfs-tools
- linux-firmware
- nfs-common
- overlayroot
- openssh-server
- curl
- net-tools
- iproute2
- systemd-sysv
- sudo
- kmod
- pciutils
- e2fsprogs
- dkms
- build-essential
- libatomic1
- libquadmath0

pxe_initramfs_modules:
- nfs
- nfsv3
- overlay
- amdgpu

pxe_k3s_data_dir: "/var/lib/rancher/k3s"

roles:
- role: pxe_controller
142 changes: 142 additions & 0 deletions deploy/ansible/roles/pxe_controller/defaults/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

# Role defaults -- override these in the playbook vars: section.
# Maps 1:1 to config.env from the shell scripts.

---
# ============================================================
# Network
# ============================================================
# REQUIRED -- set these in the playbook vars: block. They are left empty on
# purpose so no site-specific network values are baked into the repo. The role
# asserts that interface, subnet, and DNS servers are set before running.
#
# pxe_network_interface: service-machine NIC that serves PXE (e.g. "enp1s0")
# pxe_subnet: node subnet in CIDR form (e.g. "192.168.1.0/24")
# pxe_gateway: default gateway for the node subnet (informational)
# pxe_dns_servers: comma-separated DNS servers for the rootfs
pxe_network_interface: ""
pxe_subnet: ""
pxe_gateway: ""
pxe_dns_servers: ""

# ============================================================
# PXE Controller
# ============================================================
# REQUIRED -- set to your PXE controller / service host IP in the playbook.
# Left empty on purpose so site addresses are not baked into the repo;
# the role asserts this is set before running.
pxe_controller_ip: ""

# ============================================================
# k3s Server Nodes
# ============================================================
# REQUIRED -- set to your k3s server node IP(s) in the playbook.
# Left empty on purpose; the role asserts the list is non-empty.
pxe_k3s_server_ips: []

# k3s version installed into the agent rootfs. Pin this to the SAME version as
# the k3s server (see k3s_version in deploy/ansible/inventory.yml). k3s requires
# agents to be the same version as, or older than, the server. Leave empty to
# install the latest agent at build time (not recommended for a pinned server).
pxe_k3s_version: "v1.32.3+k3s1"

# ============================================================
# Credentials
# ============================================================

# Root password for rootfs (optional -- leave empty to disable password login)
# Use ansible-vault to encrypt: ansible-vault encrypt_string 'MyPass' --name 'pxe_rootfs_password'
pxe_rootfs_password: ""

# SSH public keys injected into rootfs /root/.ssh/authorized_keys.
# At least one key is REQUIRED (playbook will fail without it).
# pxe_rootfs_authorized_keys:
# - "ssh-ed25519 AAAA... you@workstation"
# - "ssh-rsa AAAA... ci@runner"
pxe_rootfs_authorized_keys: []

# ============================================================
# APT Mirror
# ============================================================
pxe_apt_mirror: "http://tw.archive.ubuntu.com/ubuntu"

# ============================================================
# Rootfs lifecycle
# ============================================================
# Force delete + rebuild rootfs from scratch (debootstrap)
pxe_rootfs_force_rebuild: true
# Run apt-get upgrade inside rootfs during chroot setup
pxe_rootfs_upgrade: false

# ============================================================
# Paths
# ============================================================
pxe_nfs_root: "/srv/nfs/rootfs"
pxe_tftp_root: "/srv/tftp"
pxe_web_root: "/var/www/html"

# ============================================================
# Rootfs build settings
# ============================================================
pxe_ubuntu_codename: "noble"

pxe_rootfs_packages:
- linux-image-6.14.0-1018-oem
- linux-headers-6.14.0-1018-oem
- initramfs-tools
- linux-firmware
- nfs-common
- overlayroot
- openssh-server
- curl
- net-tools
- iproute2
- systemd-sysv
- sudo
- kmod
- pciutils
- e2fsprogs
- dkms
- build-essential
- libatomic1
- libquadmath0

pxe_initramfs_modules:
- nfs
- nfsv3
- overlay
- amdgpu

pxe_k3s_data_dir: "/var/lib/rancher/k3s"

# ============================================================
# Host packages (installed on the PXE controller itself)
# ============================================================
pxe_host_packages:
- dnsmasq
- pxelinux
- syslinux-common
- apache2
- nfs-kernel-server
- debootstrap
- qemu-guest-agent
- grub-efi-amd64-signed
- shim-signed
39 changes: 39 additions & 0 deletions deploy/ansible/roles/pxe_controller/handlers/main.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Copyright (C) 2025 Advanced Micro Devices, Inc. All rights reserved.
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

---
- name: Restart dnsmasq
ansible.builtin.systemd:
name: dnsmasq
state: restarted
daemon_reload: true

- name: Restart nfs-kernel-server
ansible.builtin.systemd:
name: nfs-kernel-server
state: restarted

- name: Restart apache2
ansible.builtin.systemd:
name: apache2
state: restarted

- name: Reload NFS exports
ansible.builtin.command: exportfs -a
changed_when: true
Loading
Loading