From a62da20728c1df3ffb1b2ac833d96c6a8a440c74 Mon Sep 17 00:00:00 2001 From: KerwinTsaiii Date: Mon, 8 Jun 2026 10:06:53 +0800 Subject: [PATCH 1/3] Fix local ssd mount script been overwrite --- .gitignore | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 0bb458a3..9f55d1c8 100644 --- a/.gitignore +++ b/.gitignore @@ -389,9 +389,8 @@ vite.config.ts.timestamp-* dockerfiles/Courses/DL/data/FashionMNIST/raw/ *.vsix -# Local config overrides (any file containing 'local') -*local* -*.local.* +# Local config overrides +runtime/values.local.yaml # Offline bundle artifacts auplc-bundle-*/ From 4565ed2c20ef1d49fd2016c9e3cfc7970b1f860a Mon Sep 17 00:00:00 2001 From: KerwinTsaiii Date: Mon, 8 Jun 2026 10:07:08 +0800 Subject: [PATCH 2/3] Add mount-local-disk --- .../templates/mount-local-disk.service.j2 | 12 +++++++++ .../templates/mount-local-disk.sh.j2 | 25 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 deploy/ansible/roles/pxe_controller/templates/mount-local-disk.service.j2 create mode 100644 deploy/ansible/roles/pxe_controller/templates/mount-local-disk.sh.j2 diff --git a/deploy/ansible/roles/pxe_controller/templates/mount-local-disk.service.j2 b/deploy/ansible/roles/pxe_controller/templates/mount-local-disk.service.j2 new file mode 100644 index 00000000..dd5bb976 --- /dev/null +++ b/deploy/ansible/roles/pxe_controller/templates/mount-local-disk.service.j2 @@ -0,0 +1,12 @@ +[Unit] +Description=Mount local disk for k3s container image cache +Before=k3s-auto-join.service +After=local-fs.target + +[Service] +Type=oneshot +ExecStart=/usr/local/bin/mount-local-disk.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/deploy/ansible/roles/pxe_controller/templates/mount-local-disk.sh.j2 b/deploy/ansible/roles/pxe_controller/templates/mount-local-disk.sh.j2 new file mode 100644 index 00000000..15f104ba --- /dev/null +++ b/deploy/ansible/roles/pxe_controller/templates/mount-local-disk.sh.j2 @@ -0,0 +1,25 @@ +#!/bin/bash +set -euo pipefail + +K3S_DATA="{{ pxe_k3s_data_dir }}" + +DISK="" +for dev in /dev/sda /dev/vda /dev/nvme0n1; do + [ -b "$dev" ] && { DISK="$dev"; break; } +done + +if [ -z "$DISK" ]; then + echo "No local disk found, using tmpfs for k3s data" + mkdir -p "$K3S_DATA" + mount -t tmpfs -o size=4G tmpfs "$K3S_DATA" + exit 0 +fi + +if ! blkid "$DISK" | grep -q 'TYPE="ext4"'; then + echo "Formatting $DISK as ext4" + mkfs.ext4 -F -L k3s-cache "$DISK" +fi + +mkdir -p "$K3S_DATA" +mount "$DISK" "$K3S_DATA" +echo "Mounted $DISK to $K3S_DATA" From 7661621d25958a39401409f481d03ffeb78f496d Mon Sep 17 00:00:00 2001 From: KerwinTsaiii Date: Mon, 8 Jun 2026 10:43:38 +0800 Subject: [PATCH 3/3] Serve PXE k3s credentials on pxe_web_port (8080) instead of 80 The pxe_controller role served the k3s token/kubeconfig over Apache on host port 80. When the PXE controller is co-located on a k3s node, that collides with k3s Traefik / ServiceLB, which binds host ports 80/443 for cluster ingress. Move the credential endpoint to a dedicated, configurable port (pxe_web_port, default 8080): add an Apache ports.conf and a dedicated vhost, disable the default site to free port 80, and point the agent k3s-auto-join URLs and the role's verification/summary at the new port. This is purely an internal endpoint reached by PXE agents on the node subnet, so the port number is arbitrary and 80/443 are left entirely to Traefik. Co-authored-by: Cursor --- .../ansible/playbooks/pb-pxe-controller.yml | 5 +++ .../roles/pxe_controller/defaults/main.yml | 7 ++++ .../roles/pxe_controller/tasks/main.yml | 38 ++++++++++++++++++- .../templates/apache-ports.conf.j2 | 6 +++ .../templates/k3s-auto-join.sh.j2 | 4 +- .../templates/pxe-http-vhost.conf.j2 | 13 +++++++ 6 files changed, 69 insertions(+), 4 deletions(-) create mode 100644 deploy/ansible/roles/pxe_controller/templates/apache-ports.conf.j2 create mode 100644 deploy/ansible/roles/pxe_controller/templates/pxe-http-vhost.conf.j2 diff --git a/deploy/ansible/playbooks/pb-pxe-controller.yml b/deploy/ansible/playbooks/pb-pxe-controller.yml index 7bf4082d..951821ca 100644 --- a/deploy/ansible/playbooks/pb-pxe-controller.yml +++ b/deploy/ansible/playbooks/pb-pxe-controller.yml @@ -63,6 +63,11 @@ # - "ssh-ed25519 AAAA... you@workstation" # - "ssh-rsa AAAA... ci@runner" + # Apache HTTP port for serving the k3s token / kubeconfig to PXE agents. + # Defaults to 8080 (not 80) so the PXE controller can live on a k3s node + # without clashing with k3s Traefik / ServiceLB, which owns host port 80/443. + pxe_web_port: 8080 + # APT Mirror pxe_apt_mirror: "http://tw.archive.ubuntu.com/ubuntu" diff --git a/deploy/ansible/roles/pxe_controller/defaults/main.yml b/deploy/ansible/roles/pxe_controller/defaults/main.yml index 3c58119a..cc131711 100644 --- a/deploy/ansible/roles/pxe_controller/defaults/main.yml +++ b/deploy/ansible/roles/pxe_controller/defaults/main.yml @@ -93,6 +93,13 @@ pxe_nfs_root: "/srv/nfs/rootfs" pxe_tftp_root: "/srv/tftp" pxe_web_root: "/var/www/html" +# TCP port Apache listens on to serve the k3s token / kubeconfig to PXE agents. +# This is an internal-only endpoint (reachable from the node subnet), so the port +# number is arbitrary. It defaults to 8080 -- NOT 80 -- so the PXE controller can +# be co-located on a k3s node without colliding with k3s Traefik / ServiceLB, +# which binds host port 80 (and 443) for cluster ingress. +pxe_web_port: 8080 + # ============================================================ # Rootfs build settings # ============================================================ diff --git a/deploy/ansible/roles/pxe_controller/tasks/main.yml b/deploy/ansible/roles/pxe_controller/tasks/main.yml index f75e3b95..b16e2af0 100644 --- a/deploy/ansible/roles/pxe_controller/tasks/main.yml +++ b/deploy/ansible/roles/pxe_controller/tasks/main.yml @@ -431,12 +431,46 @@ changed_when: "'Enabling' in _a2enconf.stdout" notify: Restart apache2 +# Apache serves the token/kubeconfig on pxe_web_port (default 8080) instead of +# 80 so the PXE controller can be co-located on a k3s node without colliding with +# k3s Traefik / ServiceLB, which owns host port 80/443. +- name: Configure Apache listen port + ansible.builtin.template: + src: apache-ports.conf.j2 + dest: /etc/apache2/ports.conf + mode: "0644" + notify: Restart apache2 + +- name: Deploy PXE HTTP virtual host + ansible.builtin.template: + src: pxe-http-vhost.conf.j2 + dest: /etc/apache2/sites-available/pxe-http.conf + mode: "0644" + notify: Restart apache2 + +- name: Enable PXE HTTP virtual host + ansible.builtin.command: + cmd: a2ensite pxe-http + register: _a2ensite + changed_when: "'Enabling' in _a2ensite.stdout" + notify: Restart apache2 + +- name: Disable default Apache site (frees host port 80) + ansible.builtin.command: + cmd: a2dissite 000-default + register: _a2dissite + changed_when: "'Disabling' in _a2dissite.stdout" + notify: Restart apache2 + - name: Enable and start Apache ansible.builtin.systemd: name: apache2 state: started enabled: true +- name: Flush handlers for Apache + ansible.builtin.meta: flush_handlers + # ========================================================== # 12. Verify PXE server status # ========================================================== @@ -491,7 +525,7 @@ - name: Check HTTP token endpoint is reachable ansible.builtin.uri: - url: "http://127.0.0.1/k3s/" + url: "http://127.0.0.1:{{ pxe_web_port }}/k3s/" status_code: [200, 403] register: _verify_http @@ -503,7 +537,7 @@ ══════════════════════════════════════════ dnsmasq : Proxy DHCP + TFTP on {{ pxe_network_interface }} NFS : {{ pxe_nfs_root }} → {{ pxe_subnet }} - Apache : http://{{ pxe_controller_ip }}/k3s/ + Apache : http://{{ pxe_controller_ip }}:{{ pxe_web_port }}/k3s/ Kernel : {{ pxe_kernel_version | default('unknown') }} ────────────────────────────────────────── Next steps (see the Multi-AIPC PXE deployment guide): diff --git a/deploy/ansible/roles/pxe_controller/templates/apache-ports.conf.j2 b/deploy/ansible/roles/pxe_controller/templates/apache-ports.conf.j2 new file mode 100644 index 00000000..35080196 --- /dev/null +++ b/deploy/ansible/roles/pxe_controller/templates/apache-ports.conf.j2 @@ -0,0 +1,6 @@ +# Managed by Ansible (pxe_controller role) -- do not edit by hand. +# +# The PXE controller only needs plain HTTP to hand the k3s token / kubeconfig to +# netbooting agents. It listens on {{ pxe_web_port }} (not 80) so it can coexist +# with k3s Traefik / ServiceLB, which binds host port 80/443 for cluster ingress. +Listen {{ pxe_web_port }} diff --git a/deploy/ansible/roles/pxe_controller/templates/k3s-auto-join.sh.j2 b/deploy/ansible/roles/pxe_controller/templates/k3s-auto-join.sh.j2 index 64f4c8a2..53998b6a 100644 --- a/deploy/ansible/roles/pxe_controller/templates/k3s-auto-join.sh.j2 +++ b/deploy/ansible/roles/pxe_controller/templates/k3s-auto-join.sh.j2 @@ -3,8 +3,8 @@ set -euo pipefail PXE_SERVER="{{ pxe_controller_ip }}" K3S_SERVERS="{{ pxe_k3s_server_ips | join(' ') }}" -TOKEN_URL="http://${PXE_SERVER}/k3s/token" -KUBECONFIG_URL="http://${PXE_SERVER}/k3s/kubeconfig" +TOKEN_URL="http://${PXE_SERVER}:{{ pxe_web_port }}/k3s/token" +KUBECONFIG_URL="http://${PXE_SERVER}:{{ pxe_web_port }}/k3s/kubeconfig" K3S_DATA="{{ pxe_k3s_data_dir }}" HOSTNAME=$(hostname) diff --git a/deploy/ansible/roles/pxe_controller/templates/pxe-http-vhost.conf.j2 b/deploy/ansible/roles/pxe_controller/templates/pxe-http-vhost.conf.j2 new file mode 100644 index 00000000..5d40021a --- /dev/null +++ b/deploy/ansible/roles/pxe_controller/templates/pxe-http-vhost.conf.j2 @@ -0,0 +1,13 @@ +{# Managed by Ansible (pxe_controller role) -- do not edit by hand. #} + + DocumentRoot {{ pxe_web_root }} + + + Options -Indexes +FollowSymLinks + AllowOverride None + Require all granted + + + ErrorLog ${APACHE_LOG_DIR}/pxe-http-error.log + CustomLog ${APACHE_LOG_DIR}/pxe-http-access.log combined +