Migrating the Uyuni Proxy on K3s from mgrpxy to proxy-helm

1. Introduction

This document describes how to migrate a Uyuni Proxy deployed on K3s via mgrpxy install kubernetes (the legacy path) to a deployment using the proxy-helm chart directly.

The legacy path used mgrpxy as a thin wrapper around helm and installed the proxy with selector labels app: uyuni-proxy. The new path uses the proxy-helm chart directly with selector labels app.kubernetes.io/component: proxy. Since spec.selector is immutable in Kubernetes, the old deployment must be removed before the new one can be created. This causes a short downtime (approximately 30 to 60 seconds). The squid cache PVC can be preserved across the migration.

For the destination install procedure and chart values reference, see Uyuni Proxy Deployment on Kubernetes.

1.1. Prerequisites

  • The proxy is installed and running on a K3s cluster via mgrpxy install kubernetes.

  • helm (3.x) and kubectl are available on the K3s node.

  • The proxy is registered with the Uyuni Server.

2. Preparation (while the legacy install is still running)

Procedure: Preserve state and prepare the new namespace
  1. Preserve the squid PVC by switching the PV reclaim policy to Retain.

    PV=$(kubectl -n <namespace> get pvc squid-cache -o jsonpath='{.spec.volumeName}')
    kubectl patch pv $PV -p '{"spec":{"persistentVolumeReclaimPolicy":"Retain"}}'

    Replace <namespace> with the namespace where the legacy proxy is installed (often default for mgrpxy install kubernetes deployments).

  2. Extract the configuration files from the running proxy.

    mkdir -p /root/proxy-config
    kubectl -n <namespace> exec deploy/uyuni-proxy -c httpd -- cat /etc/uyuni/config.yaml > /root/proxy-config/config.yaml
    kubectl -n <namespace> exec deploy/uyuni-proxy -c httpd -- cat /etc/uyuni/httpd.yaml > /root/proxy-config/httpd.yaml
    kubectl -n <namespace> exec deploy/uyuni-proxy -c ssh   -- cat /etc/uyuni/ssh.yaml   > /root/proxy-config/ssh.yaml
  3. Prepare the namespace for the new install.

    kubectl create namespace uyuni-proxy

    The proxy-helm chart creates the proxy-cert TLS secret and the uyuni-ca ConfigMap automatically from the tarball values at install time.

3. Update Traefik (no downtime)

The legacy mgrpxy install configured the bundled K3s Traefik with entryPoint names uyuni-ssh, uyuni-publish and uyuni-request. The proxy-helm chart defaults to ssh, salt-publish and salt-request. Replace the Traefik HelmChartConfig so the new entryPoints exist before the cutover:

cat > /var/lib/rancher/k3s/server/manifests/uyuni-traefik-config.yaml << 'EOF'
apiVersion: helm.cattle.io/v1
kind: HelmChartConfig
metadata:
  name: traefik
  namespace: kube-system
spec:
  valuesContent: |-
    ports:
      ssh:
        port: 8022
        exposedPort: 8022
        protocol: TCP
        expose:
          default: true
      salt-publish:
        port: 4505
        exposedPort: 4505
        protocol: TCP
        expose:
          default: true
      salt-request:
        port: 4506
        exposedPort: 4506
        protocol: TCP
        expose:
          default: true
EOF

kubectl -n kube-system rollout restart deploy/traefik
kubectl -n kube-system rollout status deploy/traefik

Until the cutover step below, the legacy proxy is still routed through the old entryPoint names that are no longer exposed; if its IngressRouteTCP objects reference them, traffic to the legacy proxy may already be interrupted. If continuous service is required, defer this step until immediately before the cutover.

4. Cutover (downtime starts here)

Procedure: Replace the legacy deployment with the proxy-helm chart
  1. Uninstall the legacy release.

    helm -n <namespace> uninstall <release-name>

    The release name created by mgrpxy install kubernetes is typically uyuni-proxy.

  2. Release the PV from its old claim so the new chart can bind to it.

    kubectl patch pv $PV --type=json \
      -p '[{"op":"remove","path":"/spec/claimRef"}]'
  3. Install the proxy-helm chart, binding to the existing squid PV.

helm upgrade --install uyuni-proxy \
    oci://registry.opensuse.org/uyuni/proxy-helm \
    --version 2026.6.0 \
    --namespace uyuni-proxy \
    --set "registrySecret=the-scc-secret" \
    --set-file global.config=/root/proxy-config/config.yaml \
    --set-file global.httpd=/root/proxy-config/httpd.yaml \
    --set-file global.ssh=/root/proxy-config/ssh.yaml \
    --set ingress.type=traefik \
    --set ingress.class=traefik \
    --set tftp.hostNetwork=true \
    --set volumes.squid.volumeName=$PV

+

The example uses ingress.class=traefik for the case where the surrounding Traefik filters by class (for example --providers.kubernetescrd.ingressclass=traefik). On a vanilla K3S install the bundled Traefik picks up every Ingress regardless of class; set ingress.class="" instead.

5. Verify

kubectl -n uyuni-proxy get pod -w
kubectl -n uyuni-proxy get pvc          # squid-cache should be Bound to the old PV
kubectl -n uyuni-proxy logs deploy/uyuni-proxy -c httpd --tail=20

5.1. Migration complete

The proxy is now managed by the proxy-helm chart directly, reusing the legacy squid cache volume.