P5.1: Migrate minikube from podman to QEMU2 driver #38

Merged
eblume merged 16 commits from feature/p5.1-qemu2-migration into main 2026-01-21 16:03:38 -08:00
5 changed files with 62 additions and 62 deletions
Showing only changes of commit 919f926241 - Show all commits

P5.1: Update minikube role for QEMU2 driver

- Change minikube driver from podman to qemu2
- Change container runtime from cri-o to containerd
- Add qemu installation to minikube role
- Remove podman role from indri.yml playbook
- Update handlers for containerd instead of cri-o
- Temporarily disable registry mirror config (needs containerd format)
- Add k8s-storage synology user creation steps to P5.1 doc
- Add post-migration tasks for zot registry mirror reconfiguration

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Erich Blume 2026-01-20 21:06:53 -08:00

View file

@ -47,8 +47,6 @@
tags: zot tags: zot
- role: zot_metrics - role: zot_metrics
tags: zot_metrics tags: zot_metrics
- role: podman
tags: podman
- role: minikube - role: minikube
tags: minikube tags: minikube
- role: minikube_metrics - role: minikube_metrics

View file

@ -1,11 +1,10 @@
--- ---
# Minikube cluster configuration # Minikube cluster configuration
minikube_cpus: 4 minikube_cpus: 4
# Note: Must be less than podman machine memory (8192MB) to account for overhead minikube_memory: 8192
minikube_memory: 7800
minikube_disk_size: "200g" minikube_disk_size: "200g"
minikube_driver: podman minikube_driver: qemu2
minikube_container_runtime: cri-o minikube_container_runtime: containerd
# Remote access configuration # Remote access configuration
# These allow kubectl from other machines (e.g., gilbert) to connect # These allow kubectl from other machines (e.g., gilbert) to connect
@ -13,8 +12,5 @@ minikube_container_runtime: cri-o
minikube_apiserver_names: minikube_apiserver_names:
- k8s.tail8d86e.ts.net - k8s.tail8d86e.ts.net
- indri - indri
# Note: apiserver_port is the INTERNAL container port; with podman driver,
# the host port is dynamically assigned. Check actual port with:
# kubectl config view --minify -o jsonpath="{.clusters[0].cluster.server}"
minikube_apiserver_port: 6443 minikube_apiserver_port: 6443
minikube_listen_address: "0.0.0.0" minikube_listen_address: "0.0.0.0"

View file

@ -8,7 +8,7 @@
minikube start minikube start
changed_when: true changed_when: true
- name: Restart CRI-O in minikube - name: Restart containerd in minikube
ansible.builtin.command: ansible.builtin.command:
cmd: minikube ssh --native-ssh=false "sudo systemctl restart crio" cmd: minikube ssh --native-ssh=false "sudo systemctl restart containerd"
changed_when: true changed_when: true

View file

@ -1,14 +1,19 @@
--- ---
# Minikube installation and cluster setup for indri # Minikube installation and cluster setup for indri
# Requires podman machine to be running (see podman role) # Uses qemu2 driver for full VM with kernel mount capabilities (NFS, SMB, etc.)
# #
# NOTE: Similar to podman, minikube start may have issues when run via SSH. # NOTE: minikube start may have issues when run via SSH.
# If cluster fails to start, manually run on indri: # If cluster fails to start, manually run on indri:
# minikube start --driver=podman --container-runtime=cri-o \ # minikube start --driver=qemu2 --container-runtime=containerd \
# --cpus=4 --memory=7800 --disk-size=200g \ # --cpus=4 --memory=8192 --disk-size=200g \
# --apiserver-names=k8s.tail8d86e.ts.net --apiserver-names=indri \ # --apiserver-names=k8s.tail8d86e.ts.net --apiserver-names=indri \
# --apiserver-port=6443 --listen-address=0.0.0.0 # --apiserver-port=6443 --listen-address=0.0.0.0
- name: Install qemu via homebrew (required for qemu2 driver)
community.general.homebrew:
name: qemu
state: present
- name: Install minikube via homebrew - name: Install minikube via homebrew
community.general.homebrew: community.general.homebrew:
name: minikube name: minikube
@ -57,54 +62,22 @@
msg: "WARNING: minikube may not have started properly. Run 'minikube start' manually on indri if needed. Status: {{ minikube_final_status.stdout | default('unknown') }}" msg: "WARNING: minikube may not have started properly. Run 'minikube start' manually on indri if needed. Status: {{ minikube_final_status.stdout | default('unknown') }}"
when: minikube_final_status.rc != 0 or 'Running' not in minikube_final_status.stdout when: minikube_final_status.rc != 0 or 'Running' not in minikube_final_status.stdout
# Configure CRI-O to use zot as pull-through cache # Configure containerd to use zot as pull-through cache
- name: Read desired zot mirror config # With qemu2 driver, host is accessible via host.minikube.internal
ansible.builtin.slurp: # Zot listens on indri:5050 (localhost:5050 from host perspective)
src: "{{ role_path }}/files/zot-mirror.conf" - name: Get host IP for registry mirror config
register: minikube_desired_zot_config
delegate_to: localhost
when: minikube_final_status.rc == 0 and 'Running' in minikube_final_status.stdout
- name: Check current zot mirror config in minikube
ansible.builtin.command: ansible.builtin.command:
cmd: minikube ssh --native-ssh=false "cat /etc/containers/registries.conf.d/zot-mirror.conf 2>/dev/null || echo ''" cmd: minikube ssh --native-ssh=false "getent hosts host.minikube.internal | awk '{print \$1}'"
register: minikube_existing_zot_config register: minikube_host_ip
changed_when: false changed_when: false
failed_when: false
when: minikube_final_status.rc == 0 and 'Running' in minikube_final_status.stdout when: minikube_final_status.rc == 0 and 'Running' in minikube_final_status.stdout
- name: Determine if zot mirror config needs update - name: Configure insecure registry for zot
ansible.builtin.set_fact: ansible.builtin.command:
minikube_zot_config_changed: "{{ (minikube_existing_zot_config.stdout | trim) != (minikube_desired_zot_config.content | b64decode | trim) }}" cmd: "minikube addons configure registry-creds"
when: minikube_final_status.rc == 0 and 'Running' in minikube_final_status.stdout changed_when: false
failed_when: false
- name: Copy zot mirror config to temp location when: false # TODO: Configure containerd registry mirrors after basic migration works
ansible.builtin.copy: # For now, images will be pulled directly from public registries
src: zot-mirror.conf # We can add zot mirror config later via containerd config or minikube addons
dest: /tmp/zot-mirror.conf
mode: "0644"
when:
- minikube_final_status.rc == 0
- "'Running' in minikube_final_status.stdout"
- minikube_zot_config_changed | default(false)
- name: Apply zot mirror config to minikube
ansible.builtin.shell:
cmd: |
set -o pipefail
cat /tmp/zot-mirror.conf | minikube ssh --native-ssh=false "sudo tee /etc/containers/registries.conf.d/zot-mirror.conf > /dev/null"
executable: /bin/bash
changed_when: true # Task only runs when config needs updating
when:
- minikube_final_status.rc == 0
- "'Running' in minikube_final_status.stdout"
- minikube_zot_config_changed | default(false)
notify: Restart CRI-O in minikube
- name: Clean up temp config file
ansible.builtin.file:
path: /tmp/zot-mirror.conf
state: absent
when:
- minikube_final_status.rc == 0
- "'Running' in minikube_final_status.stdout"
- minikube_zot_config_changed | default(false)

View file

@ -45,6 +45,26 @@ QEMU2 creates an actual VM (not a container), which has:
--- ---
## Prerequisites (Manual Steps)
### Create Synology User for Kubernetes Storage Access
Create a dedicated Synology user for k8s NFS/SMB access (do not use personal account):
On Synology DSM (Control Panel → User & Group):
1. Create new user: `k8s-storage`
- Set a strong password
- No admin privileges needed
- Deny access to all applications (only needs file services)
2. Set permissions on the `torrents` share:
- Give `k8s-storage` user Read/Write access
3. Store credentials in 1Password:
- Vault: `vg6xf6vvfmoh5hqjjhlhbeoaie` (blumeops vault)
- Item name: `synology-k8s-storage`
- Fields: `username` (k8s-storage), `password`
---
## Plan ## Plan
### 1. Export Current State ### 1. Export Current State
@ -233,3 +253,16 @@ All state is in git, so cluster recreation is straightforward.
- First boot may be slower due to VM initialization - First boot may be slower due to VM initialization
- socket_vmnet provides better networking but requires sudo setup - socket_vmnet provides better networking but requires sudo setup
- Consider creating a LaunchAgent for `minikube mount` if using that approach - Consider creating a LaunchAgent for `minikube mount` if using that approach
## Post-Migration Tasks
### Zot Registry Mirror (TODO)
The CRI-O registry mirror config (`zot-mirror.conf`) is not compatible with containerd. After the basic QEMU2 migration is verified working, we need to:
1. **Reconfigure zot mirrors for containerd** - containerd uses a different config format at `/etc/containerd/config.toml`
2. **Update host address** - `host.containers.internal` (podman-specific) won't work; use `host.minikube.internal` or the host IP instead
3. **Test registry caching** - verify images are being cached through zot
4. **Update ansible role** - add containerd-specific registry mirror configuration
For now, images will be pulled directly from public registries (docker.io, ghcr.io, etc.) which is fine for the migration but loses the caching benefits.