ska-cicd-deploy-minikube

:bulb: Deploy a Minikube development environment using make.

Table of Contents

[[TOC]]

Summary

This repo provides a basic recipe and very opinionated recipe for deploying Minikube as a development environment that will support the standard features required for emulating the SKA testing and production environments. Please note the OS specific variations at the end of this README. Also note that this repository gets updated on a semi-regular basis in order to track the versions of tools, amongst other things, from:

  • https://github.com/kubernetes/minikube/releases

  • https://github.com/helm/helm/releases

  • https://registry.hub.docker.com/_/haproxy

  • https://kubernetes.io/releases/

By default, docker is used as the driver on all platforms. It is possible to use podman by passing DRIVER=podman to all make invocations, though this is not recommended as podman support on Linux can be unreliable.

Also, by default, a set of addons are automatically enabled, these are:

  • logviewer - simple logview available on port 32000 - browse with sensible-browser http://$(minikube ip):32000

  • metrics-server - simple metrics server

  • ingress - NGINX based Ingress Controller for exposing HTTP/HTTPS services

  • metallb - enable creation of LoadBlancer type Service resources to expose application ports out of Kubernetes. This is deployed in conjunction with a DNS responder (extdns) that can be integrated with the local users DNS settings to have automatic name resolution for these services.

:zap: Note: if you need any help with getting this going, then please provide the full output of any commands you run along with the details of your OS and version in the #team-system-support Slack channel. It also helps to check that you have pulled the latest version of this repository as it does change every 2-3 months.

Platform Support

Supported Platforms

| Platform | Versions | Default Driver | HAProxy | Auto DNS | |———-|———-|—————|———|———-| | Ubuntu Linux | 22.04, 24.04, 26.04 | docker | Yes | Yes (systemd-resolved) | | macOS Apple Silicon | M1 / M2 / M3 (arm64) | docker | No | No | | Windows WSL2 | Ubuntu 22.04, 24.04 | docker | No | No |

On macOS and WSL2, HAProxy and automatic DNS configuration are not deployed. Use minikube ip or kubectl port-forward to reach cluster services.

Prerequisites

All platforms require the container runtime to be installed before running make all. All other tools are installed automatically by make all or by separately running make setup first.

Tool Installation Path (EXE_DIR)

Tools are installed to ~/.local/bin by default (no sudo required). Ensure this is on your $PATH:

# Add to ~/.bashrc or ~/.zshrc
export PATH="$HOME/.local/bin:$PATH"

To install to a different location (e.g. /usr/local/bin):

make all EXE_DIR=/usr/local/bin

Diagnostics

make platform-info   # print detected OS, driver, EXE_DIR, PATH check
make verify          # confirm tools installed and cluster is healthy

Manual Test Checklist (macOS / WSL2)

Run these steps to confirm a working installation:

# 1. (macOS only) Ensure Docker Desktop is running

# 2. Deploy
make all

# 3. Check platform detection
make platform-info

# 4. Verify tools and cluster
make verify

# 5. Confirm a node is Ready
kubectl get nodes

# 6. Get cluster IP (use instead of DNS)
minikube --profile minikube ip

# 7. Clean up
make clean

Known Limitations on macOS and WSL2

  • No HAProxy — use minikube tunnel or kubectl port-forward to expose services

  • No automatic DNS — resolve services via minikube ip; DNS entries must be added manually if needed

How to Use

:red_exclamation_mark: It is very important that you check the Caveats section below to ensure that no major issues - that might affect the stability of the rest of the OS - are encountered.

:red_exclamation_mark: Before you continue, see the OS Variations section below to ensure your dependencies are satisfied.

Checkout ska-cicd-deploy-minikube (this repo) with:

git clone git@gitlab.com:ska-telescope/sdi/ska-cicd-deploy-minikube.git
cd ska-cicd-deploy-minikube

Now explore, using:

$ make minikube-vars
Minikube Installed: Yes!
Helm Installed:     Yes!
DRIVER:             podman
RUNTIME:            docker
HAPROXY_ENGINE:     docker
ADD_ARGS:            --addons=logviewer
ADDONS:             --addons=metrics-server --addons=ingress --addons=csi-hostpath-driver --addons=volumesnapshots
CILIUM:             yes
KYVERNO:            yes
CPUS:               6
MEM:                8192
OS_NAME:            linux
OS_ARCH:            x86_64
OS_BIN:             amd64
EXE_DIR:            /usr/local/bin
SUDO_FOR_EXE_DIR:   sudo --preserve-env=http_proxy --preserve-env=https_proxy
IPADDR:             192.168.1.4
MINIKUBE_IP:        * Profile minikube not found. Run minikube profile list to view all profiles.   To start a cluster, run: minikube start
HOSTNAME:           wattle
FQDN:               wattle.local.net
MOUNT_FROM:         /srv
MOUNT_TO:           /srv
PROXY_VERSION:      2.9
PROXY_CONFIG:       /home/piers/.minikube/minikube-nginx-haproxy.cfg
MINIKUBE_VERSION:   v1.32.0
KUBERNETES_VERSION: v1.29.1
KUBERNETES_SERVER_VERSION: v1.29.1
HELM_VERSION:       v3.14.0
HELMFILE_VERSION:   0.160.0
YQ_VERSION:         4.40.5
KYVERNO_VERSION:    1.11.4
CILIUM_CLI_VERSION: 0.15.20
INGRESS:            http://* Profile minikube not found. Run minikube profile list to view all profiles. To start a cluster, run: minikube start
USE_CACHE:          yes
CACHE_DATA:         /home/piers/.minikube/registry_cache
Minikube status:
* Profile "minikube" not found. Run "minikube profile list" to view all profiles.
  To start a cluster, run: "minikube start"

Inspect the help and defaults with:

$ make
preparing the help
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'

------
SECTION: Makefile
MAKE TARGETS:
all                            🔥 do setup and install
bats-reinstall                 reinstall bats-core dependencies
bats-test                      Run unit tests using BATS
clean                          alias for minikube-clean
minikube-cache                 docker image caching proxy
minikube-clean-cache           💀 clean the cache - WARNING you must make minikube-clean Minikube first!!!!
minikube-clean                 💀 Delete Minikube cluster etc. - **caution** there is no going back!
minikube-dig-extdns            Dig CoreDNS k8s_external responder
minikube-extdns                Deploy CoreDNS k8s_external responder
minikube-haproxy               Setup haproxy to present the Ingress controller to the outside world
minikube-install               ✨ Install Minikube, Ingress Controller, Metal LB, and HAProxy (on Linux)
minikube-install-podman        ✨ Install podman tools, if this Makefile supports your OS.
cluster-kubeconfig             print KUBECONFIG for Minikube and swapping to external IP (try: make cluster-kubeconfig > minikube_config; export KUBECONFIG=$(pwd)/minikube_config)
minikube-kyverno               install Kyverno in the cluster
minikube-load-images           load images from the charts listed in K8S_CHARTS
minikube-node-ports            list potential node ports from the running Minikube cluster
minikube-registry              Setup a local Docker Registry integrated with Minikube
minikkube-setup                ✨ install command line tools for Minikube, kubectl, helm, k9s and yq dependencies
minikube-tango-operator        install ska-tango-operator in the cluster
cluster-test                   🔎 run an interactive  test deployment
minikube-tools                 install HAProxy
minikube-vars                  list the public vars and Minikube status

MAKE VARS (+defaults):
ADD_ARGS                       ## Additional ARGS passed to minikube start
ADDONS                         --addons=metrics-server --addons=ingress
BIN_DIR                        /usr/bin## the directory where the $(DRIVER) is installed eg: docker/podman
CACHE_VERSION                  0.6.4## local registry cache based on NGINX https://hub.docker.com/r/rpardini/docker-registry-proxy/tags
CI_JOB_ID                      local
CILIUM                         ## add CILIUM=yes to use Cilium as the CNI
CILIUM_CLI_VERSION             0.15.20## Kyverno cli stable version to install https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt
CPUS                           4## Number of (v)CPUs to allocate to Minikube
DRIVER                         docker
DRIVER                         hyperkit
DRIVER                         podman## Virtualisation layer used to host minikube - default podman for Linux, and hyperkit or docker for MacOS
EXE_DIR                        $(shell which minikube 2>/dev/null | sed s=/minikube$$==)## The directory where binaries will be installed
FLAGS                          ## Additional flags to pass to minikube
FQDN                           $(HOST).local.net
HAPROXY_ENGINE                 $(RUNTIME)## haproxy container engine for local host deployment of proxy
HELMFILE_VERSION               0.160.0## Helmfile tool version to install https://github.com/helmfile/helmfile/releases
HELM_VERSION                   v3.14.0## Helm tool version to install https://github.com/helm/helm/releases
HOSTNAME                       $(HOST)
IPADDR                         $(IP)
K8S_CHART_PARAMS               ## Parameters to pass to helm template for image discovery
K8S_CHARTS                     ska-tango-base ## Charts to parse for images to preload
K9S_VERSION                    v0.31.7## k9s tool version to install https://github.com/derailed/k9s/releases
KUBERNETES_SERVER_VERSION      $(KUBERNETES_VERSION)## Kubernetes server version to be used. Normally a sane default is automatically chosen.
KUBERNETES_VERSION             v1.29.1## Kubernetes version to bootup https://kubernetes.io/releases/
KYVERNO_NAMESPACE              kyverno
KYVERNO_VERSION                1.11.4## Kyverno cli version to install https://github.com/kyverno/kyverno/releases
MEM                            8192## Amount of RAM to allocate to Minikube (MB)
METALLB_VERSION                0.14.3## MetalLB LoadBalancer version to install https://github.com/metallb/metallb/releases
MINIKUBE_HOME                  $(HOME)
MINIKUBE_NETWORK               host## Minikube network name (Docker Networking)
MINIKUBE_NETWORK               minikube## Minikube network name (Docker Networking)
MINIKUBE_VERSION               v1.32.0## Minikube tool version to install https://github.com/kubernetes/minikube/releases
MOUNT_FROM                     $(MOUNT_FROM_DIR)## Source directory to mount into Minikube VM(or CnC)
MOUNT_TO                       /srv##Target directory to mount into Minikube VM(or CnC)
NODES                          1## Number of Nodes for Minikube to create - should always be 1
PROXY_VERSION                  2.9## haproxy version to install for frontend proxy https://hub.docker.com/_/haproxy/tags
RUNTIME                        docker## How containers are run within minikube - docker, cri-o or containerd
SKA_TANGO_OPERATOR_CHART       skatelescope/ska-tango-operator
SKA_TANGO_OPERATOR_ENABLED     true
SKA_TANGO_OPERATOR_NAMESPACE   ska-tango-operator
USE_CACHE                      ## Deploy a local NGiNX based image cache
YQ_VERSION                     4.40.5## yq tool version to install https://github.com/mikefarah/yq/releases

Install the tools and deploy Kubernetes

The complete install of tools (dependencies: minikube, kubectl, helm, and k9s), and the deployment of a Minikube cluster can be done with:

$ make all
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
error: context "minikube" does not exist
CoreDNS with k8s_external plugin is listening on: :53
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Cleaning up with DRIVER: docker
🤷  Profile "minikube" not found. Run "minikube profile list" to view all profiles.
👉  To start a cluster, run: "minikube start"
🙄  "minikube" profile does not exist, trying anyways.
💀  Removed all traces of the "minikube" cluster.
Minikube v1.38.1 already installed
kubectl v1.35.3 already installed
helm v3.20.1 already installed
helm4 v4.1.3 already installed
helmfile 1.4.3 already installed
K9s v0.50.18 already installed
# https://github.com/int128/kubelogin/blob/master/docs/setup.md
kubectl-oidc_login 1.36.0 already installed
yq 4.52.5 already installed
cilium 0.19.2 already installed
Kind v0.31.0 already installed
regctl v0.11.2 already installed
oras 1.3.1 already installed
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Starting a new registry_cache in /home/piers/.minikube/registry_cache ...
00791410b0ff4156fd240da0c05454829c679067e29540c9bacd9432dbe58c59
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Minikube status:
🤷  Profile "minikube" not found. Run "minikube profile list" to view all profiles.
👉  To start a cluster, run: "minikube start"
Minikube not running, continuing...
Using driver: docker with runtime: docker
Extra ARGS set:  --docker-env http_proxy=http://192.168.178.23:3128 --docker-env https_proxy=http://192.168.178.23:3128 --docker-env no_proxy=192.168.178.23,localhost,127.0.0.1,10.96.0.0/12,192.168.59.0/24,192.168.39.0/24,192.168.49.0/24,172.17.0.1/16,10.153.0.0/17  
Local mount: /srv:/srv
😄  minikube v1.38.1 on Ubuntu 26.04
❗  Specified Kubernetes version 1.35.3 is newer than the newest supported version: v1.35.1. Use `minikube config defaults kubernetes-version` for details.
❗  Specified Kubernetes version 1.35.3 not found in Kubernetes version list
🤔  Searching the internet for Kubernetes version...
✅  Kubernetes version 1.35.3 found in GitHub version list
✨  Using the docker driver based on user configuration
❗  Starting v1.39.0, minikube will default to "containerd" container runtime. See #21973 for more info.
❗  With --network-plugin=cni, you will need to provide your own CNI. See --cni flag as a user-friendly alternative
📌  Using Docker driver with root privileges
👍  Starting "minikube" primary control-plane node in "minikube" cluster
🚜  Pulling base image v0.0.50 ...
🔥  Creating docker container (CPUs=8, Memory=16384MB) ...
🐳  Preparing Kubernetes v1.35.3 on Docker 29.2.1 ...
    ▪ env http_proxy=http://192.168.178.23:3128
    ▪ env https_proxy=http://192.168.178.23:3128
    ▪ env no_proxy=192.168.178.23,localhost,127.0.0.1,10.96.0.0/12,192.168.59.0/24,192.168.39.0/24,192.168.49.0/24,172.17.0.1/16,10.153.0.0/17
    ▪ kubeadm.pod-network-cidr=10.0.0.0/16
🔎  Verifying Kubernetes components...
    ▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟  Enabled addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
daemonset.apps "kube-proxy" deleted from kube-system namespace
configmap "kube-proxy" deleted from kube-system namespace
kubectl --context minikube apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.5.1/config/crd/standard/gateway.networking.k8s.io_gatewayclasses.yaml
customresourcedefinition.apiextensions.k8s.io/gatewayclasses.gateway.networking.k8s.io created
kubectl --context minikube apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.5.1/config/crd/standard/gateway.networking.k8s.io_gateways.yaml
customresourcedefinition.apiextensions.k8s.io/gateways.gateway.networking.k8s.io created
kubectl --context minikube apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.5.1/config/crd/standard/gateway.networking.k8s.io_httproutes.yaml
customresourcedefinition.apiextensions.k8s.io/httproutes.gateway.networking.k8s.io created
kubectl --context minikube apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.5.1/config/crd/standard/gateway.networking.k8s.io_referencegrants.yaml
customresourcedefinition.apiextensions.k8s.io/referencegrants.gateway.networking.k8s.io created
kubectl --context minikube apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.5.1/config/crd/standard/gateway.networking.k8s.io_grpcroutes.yaml
customresourcedefinition.apiextensions.k8s.io/grpcroutes.gateway.networking.k8s.io created
kubectl --context minikube apply -f https://raw.githubusercontent.com/kubernetes-sigs/gateway-api/v1.3.0/config/crd/experimental/gateway.networking.k8s.io_tlsroutes.yaml
customresourcedefinition.apiextensions.k8s.io/tlsroutes.gateway.networking.k8s.io created
🔮 Auto-detected Kubernetes kind: minikube
ℹ️  Using Cilium version 1.19.2
ℹ️  Using cluster name "minikube"
🔮 Auto-detected kube-proxy has not been installed
ℹ️  Cilium will fully replace all functionalities of kube-proxy
"jetstack" already exists with the same configuration, skipping
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "jetstack" chart repository
Update Complete. ⎈Happy Helming!⎈
Release "cert-manager" does not exist. Installing it now.
NAME: cert-manager
LAST DEPLOYED: Sun May 17 18:42:41 2026
NAMESPACE: cert-manager
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
cert-manager v1.16.2 has been deployed successfully!

In order to begin issuing certificates, you will need to set up a ClusterIssuer
or Issuer resource (for example, by creating a 'letsencrypt-staging' issuer).

More information on the different types of issuers and how to configure them
can be found in our documentation:

https://cert-manager.io/docs/configuration/

For information on how to configure cert-manager to automatically provision
Certificates for Ingress resources, take a look at the `ingress-shim`
documentation:

https://cert-manager.io/docs/usage/ingress/
clusterrole.rbac.authorization.k8s.io/cilium-operator patched
kubectl -n kube-system get pods -l k8s-app=cilium
NAME           READY   STATUS    RESTARTS   AGE
cilium-dnn9d   1/1     Running   0          39s
pod/cilium-dnn9d condition met

Checking encryption:
Encryption:       Wireguard       [NodeEncryption: Disabled, cilium_wg0 (Pubkey: /z1maZBPxLmllVNx6E8u+4dCOWmo136aBow+0qiiF0c=, Port: 51871, Peers: 0)]

echo "${API_GATEWAY_CONFIG}" | kubectl --context minikube -n kube-system apply -f -
Warning: resource gatewayclasses/cilium is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
gatewayclass.gateway.networking.k8s.io/cilium configured
gateway.gateway.networking.k8s.io/cilium-gateway-http created
deployment.apps/cilium-operator restarted
Name:         cilium-gateway-http
Namespace:    kube-system
Labels:       <none>
Annotations:  <none>
API Version:  gateway.networking.k8s.io/v1
Kind:         Gateway
Metadata:
  Creation Timestamp:  2026-05-17T17:43:20Z
  Generation:          1
  Resource Version:    947
  UID:                 94d0afa3-3a80-4598-8e6a-998234f9c87e
Spec:
  Gateway Class Name:  cilium
  Listeners:
    Allowed Routes:
      Namespaces:
        From:  All
    Name:      http-gw
    Port:      80
    Protocol:  HTTP
Status:
  Conditions:
    Last Transition Time:  2026-05-17T17:43:20Z
    Message:               Gateway successfully scheduled
    Observed Generation:   1
    Reason:                Accepted
    Status:                True
    Type:                  Accepted
    Last Transition Time:  2026-05-17T17:43:20Z
    Message:               Gateway waiting for address
    Observed Generation:   1
    Reason:                AddressNotAssigned
    Status:                False
    Type:                  Programmed
  Listeners:
    Attached Routes:  0
    Conditions:
      Last Transition Time:  2026-05-17T17:43:20Z
      Message:               Resolved Refs
      Observed Generation:   1
      Reason:                ResolvedRefs
      Status:                True
      Type:                  ResolvedRefs
      Last Transition Time:  2026-05-17T17:43:20Z
      Message:               Listener Accepted
      Observed Generation:   1
      Reason:                Accepted
      Status:                True
      Type:                  Accepted
      Last Transition Time:  2026-05-17T17:43:20Z
      Message:               Address not ready yet
      Observed Generation:   1
      Reason:                Pending
      Status:                False
      Type:                  Programmed
    Name:                    http-gw
    Supported Kinds:
      Group:  gateway.networking.k8s.io
      Kind:   HTTPRoute
      Group:  gateway.networking.k8s.io
      Kind:   GRPCRoute
Events:       <none>
Name:                     cilium-gateway-cilium-gateway-http
Namespace:                kube-system
Labels:                   gateway.networking.k8s.io/gateway-name=cilium-gateway-http
                          io.cilium.gateway/owning-gateway=cilium-gateway-http
Annotations:              <none>
Selector:                 <none>
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.111.90.178
IPs:                      10.111.90.178
Port:                     port-80  80/TCP
TargetPort:               80/TCP
NodePort:                 port-80  32322/TCP
Endpoints:                <none>
Session Affinity:         None
External Traffic Policy:  Cluster
Internal Traffic Policy:  Cluster
Events:                   <none>
# https://gateway-api.f5se.io/guides/allowedroutes/#gateway-and-route-attachment-spec-allowedroutes
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
💡  metrics-server is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
    ▪ Using image registry.k8s.io/metrics-server/metrics-server:v0.8.1
🌟  The 'metrics-server' addon is enabled
💡  csi-hostpath-driver is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
❗  [WARNING] For full functionality, the 'csi-hostpath-driver' addon requires the 'volumesnapshots' addon to be enabled.

You can enable 'volumesnapshots' addon by running: 'minikube addons enable volumesnapshots'

    ▪ Using image registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.6.0
    ▪ Using image registry.k8s.io/sig-storage/hostpathplugin:v1.9.0
    ▪ Using image registry.k8s.io/sig-storage/livenessprobe:v2.8.0
    ▪ Using image registry.k8s.io/sig-storage/csi-resizer:v1.6.0
    ▪ Using image registry.k8s.io/sig-storage/csi-snapshotter:v6.1.0
    ▪ Using image registry.k8s.io/sig-storage/csi-provisioner:v3.3.0
    ▪ Using image registry.k8s.io/sig-storage/csi-attacher:v4.0.0
    ▪ Using image registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.7.0
🔎  Verifying csi-hostpath-driver addon...
🌟  The 'csi-hostpath-driver' addon is enabled
💡  volumesnapshots is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
    ▪ Using image registry.k8s.io/sig-storage/snapshot-controller:v6.1.0
🌟  The 'volumesnapshots' addon is enabled
💡  csi-hostpath-driver is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
    ▪ Using image registry.k8s.io/sig-storage/csi-node-driver-registrar:v2.6.0
    ▪ Using image registry.k8s.io/sig-storage/hostpathplugin:v1.9.0
    ▪ Using image registry.k8s.io/sig-storage/livenessprobe:v2.8.0
    ▪ Using image registry.k8s.io/sig-storage/csi-resizer:v1.6.0
    ▪ Using image registry.k8s.io/sig-storage/csi-snapshotter:v6.1.0
    ▪ Using image registry.k8s.io/sig-storage/csi-provisioner:v3.3.0
    ▪ Using image registry.k8s.io/sig-storage/csi-attacher:v4.0.0
    ▪ Using image registry.k8s.io/sig-storage/csi-external-health-monitor-controller:v0.7.0
🔎  Verifying csi-hostpath-driver addon...
🌟  The 'csi-hostpath-driver' addon is enabled
💡  volumesnapshots is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
    ▪ Using image registry.k8s.io/sig-storage/snapshot-controller:v6.1.0
🌟  The 'volumesnapshots' addon is enabled
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Apply the standard storage classes
kubectl --context minikube apply -f ./resources/sc.yaml
storageclass.storage.k8s.io/nfs created
storageclass.storage.k8s.io/nfss1 created
storageclass.storage.k8s.io/block created
storageclass.storage.k8s.io/bds1 created
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
# @kubectl --context minikube get configmap kube-proxy -n kube-system -o yaml | \
# 	sed -e "s/strictARP: false/strictARP: true/" | \
# 	kubectl --context minikube apply -f - -n kube-system
node/minikube unlabeled
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Install metallb
kubectl --context minikube apply -f https://raw.githubusercontent.com/metallb/metallb/v0.15.3/config/manifests/metallb-native.yaml
namespace/metallb-system created
customresourcedefinition.apiextensions.k8s.io/bfdprofiles.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgpadvertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/bgppeers.metallb.io created
customresourcedefinition.apiextensions.k8s.io/communities.metallb.io created
customresourcedefinition.apiextensions.k8s.io/configurationstates.metallb.io created
customresourcedefinition.apiextensions.k8s.io/ipaddresspools.metallb.io created
customresourcedefinition.apiextensions.k8s.io/l2advertisements.metallb.io created
customresourcedefinition.apiextensions.k8s.io/servicebgpstatuses.metallb.io created
customresourcedefinition.apiextensions.k8s.io/servicel2statuses.metallb.io created
serviceaccount/controller created
serviceaccount/speaker created
role.rbac.authorization.k8s.io/controller created
role.rbac.authorization.k8s.io/pod-lister created
clusterrole.rbac.authorization.k8s.io/metallb-system:controller created
clusterrole.rbac.authorization.k8s.io/metallb-system:speaker created
rolebinding.rbac.authorization.k8s.io/controller created
rolebinding.rbac.authorization.k8s.io/pod-lister created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:controller created
clusterrolebinding.rbac.authorization.k8s.io/metallb-system:speaker created
configmap/metallb-excludel2 created
secret/metallb-webhook-cert created
service/metallb-webhook-service created
deployment.apps/controller created
daemonset.apps/speaker created
validatingwebhookconfiguration.admissionregistration.k8s.io/metallb-webhook-configuration created
Wait for metallb to be ready
pod/controller-66bdd896c6-jt4cj condition met
pod/speaker-522bm condition met
Apply the metallb address pool and L2 advertisement - prefix: 192.168.49
namespace/metallb-system configured
ipaddresspool.metallb.io/development created
l2advertisement.metallb.io/l2-advert created
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Installing Ingress Controller:
"ingress-nginx" already exists with the same configuration, skipping
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "ingress-nginx" chart repository
Update Complete. ⎈Happy Helming!⎈
Release "ingress-nginx" does not exist. Installing it now.
NAME: ingress-nginx
LAST DEPLOYED: Sun May 17 18:45:01 2026
NAMESPACE: ingress-nginx
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None
NOTES:
The ingress-nginx controller has been installed.
Get the application URL by running these commands:
  export HTTP_NODE_PORT=30080
  export HTTPS_NODE_PORT=30443
  export NODE_IP="$(kubectl get nodes --output jsonpath="{.items[0].status.addresses[1].address}")"

  echo "Visit http://${NODE_IP}:${HTTP_NODE_PORT} to access your application via HTTP."
  echo "Visit https://${NODE_IP}:${HTTPS_NODE_PORT} to access your application via HTTPS."

An example Ingress that makes use of the controller:
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: example
    namespace: foo
  spec:
    ingressClassName: nginx
    rules:
      - host: www.example.com
        http:
          paths:
            - pathType: Prefix
              backend:
                service:
                  name: exampleService
                  port:
                    number: 80
              path: /
    # This section is only required if TLS is to be enabled for the Ingress
    tls:
      - hosts:
        - www.example.com
        secretName: example-tls

If TLS is enabled for the Ingress, a Secret containing the certificate and key must also be provided:

  apiVersion: v1
  kind: Secret
  metadata:
    name: example-tls
    namespace: foo
  data:
    tls.crt: <base64 encoded cert>
    tls.key: <base64 encoded key>
  type: kubernetes.io/tls
pod/ingress-nginx-controller-56f47c86d-brlsm condition met
# install the NGINX OSS controller
Installing Nginx Ingress Controller OSS:
Release "nginx-ingress-oss" does not exist. Installing it now.
Pulled: ghcr.io/nginx/charts/nginx-ingress:2.5.1
Digest: sha256:8f69800e1e89006221c1b58897e00d1790b9e523dcf7e01fd9e6b2d134cc91b1
NAME: nginx-ingress-oss
LAST DEPLOYED: Sun May 17 18:45:30 2026
NAMESPACE: nginx-ingress-oss
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
NGINX Ingress Controller 5.4.1 has been installed.

For release notes, see: https://docs.nginx.com/nginx-ingress-controller/changelog/

For Helm installation instructions, see: https://docs.nginx.com/nginx-ingress-controller/install/helm/
Installing HAProxy Ingress Controller:
"haproxytech" already exists with the same configuration, skipping
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "haproxytech" chart repository
Update Complete. ⎈Happy Helming!⎈
Release "haproxy-kubernetes-ingress" does not exist. Installing it now.
NAME: haproxy-kubernetes-ingress
LAST DEPLOYED: Sun May 17 18:45:31 2026
NAMESPACE: haproxy-controller
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
HAProxy Kubernetes Ingress Controller has been successfully installed.

Controller image deployed is: "docker.io/haproxytech/kubernetes-ingress:3.2.6".
Your controller is of a "Deployment" kind. Your controller service is running as a "LoadBalancer" type.
RBAC authorization is enabled.
Controller ingress.class is set to "haproxy" so make sure to use same annotation for
Ingress resource.

Service ports mapped are:
  - name: admin
    containerPort: 6060
    protocol: TCP
  - name: http
    containerPort: 8080
    protocol: TCP
  - name: https
    containerPort: 8443
    protocol: TCP
  - name: stat
    containerPort: 1024
    protocol: TCP
  - name: quic
    containerPort: 8443
    protocol: UDP

Node IP can be found with:
  $ kubectl --namespace haproxy-controller get nodes -o jsonpath="{.items[0].status.addresses[1].address}"

The following ingress resource routes traffic to pods that match the following:
  * service name: web
  * client's Host header: webdemo.com
  * path begins with /

  ---
  apiVersion: networking.k8s.io/v1
  kind: Ingress
  metadata:
    name: web-ingress
    namespace: default
    annotations:
      ingress.class: "haproxy"
  spec:
    rules:
    - host: webdemo.com
      http:
        paths:
        - path: /
          backend:
            serviceName: web
            servicePort: 80

In case that you are using multi-ingress controller environment, make sure to use ingress.class annotation and match it
with helm chart option controller.ingressClass.

For more examples and up to date documentation, please visit:
  * Helm chart documentation: https://github.com/haproxytech/helm-charts/tree/main/kubernetes-ingress
  * Controller documentation: https://www.haproxy.com/documentation/kubernetes/latest/
  * Annotation reference: https://github.com/haproxytech/kubernetes-ingress/tree/master/documentation
  * Image parameters reference: https://github.com/haproxytech/kubernetes-ingress/blob/master/documentation/controller.md
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Patch coredns to selected version
deployment.apps/coredns image updated
kubectl --context minikube get configmap coredns -n kube-system -o yaml | \
	sed -e "s/forward . \/etc\/resolv.conf/forward . 192.168.200.1 /" | \
	kubectl --context minikube apply -f - -n kube-system
Warning: resource configmaps/coredns is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
configmap/coredns configured
deployment.apps/coredns restarted
Check that CoreDNS is properly started:
deployment.apps/coredns condition met
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Add the coredns chart
"coredns" already exists with the same configuration, skipping
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "coredns" chart repository
Update Complete. ⎈Happy Helming!⎈
Setup coredns k8s_external responder
Apply the metallb config map - prefix: 192.168.49
Release "extdns" does not exist. Installing it now.
level=INFO msg="warning: destination for coredns.hpa.metrics is a table. Ignoring non-table value ([])"
NAME: extdns
LAST DEPLOYED: Sun May 17 18:45:41 2026
NAMESPACE: extdns
STATUS: deployed
REVISION: 1
DESCRIPTION: Install complete
TEST SUITE: None
NOTES:
CoreDNS is now running in the cluster.
It can be accessed using the below endpoint
  NOTE: It may take a few minutes for the LoadBalancer IP to be available.
        You can watch the status by running 'kubectl get svc -w extdns-coredns'

    export SERVICE_IP=$(kubectl get svc --namespace extdns extdns-coredns -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    echo $SERVICE_IP

It can be tested with the following:

1. Launch a Pod with DNS tools:

kubectl run -it --rm --restart=Never --image=infoblox/dnstools:latest dnstools

2. Query the DNS server:

/ # host kubernetes
Waiting for external DNS responder to start
pod/extdns-coredns-7b588b5f7d-5njw6 condition met
CoreDNS with k8s_external plugin is listening on: 192.168.49.99:53

; <<>> DiG 9.20.18-1ubuntu2-Ubuntu <<>> @192.168.49.99 -p 53 extdns-coredns.extdns.svc.cluster.local
; (1 server found)
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 44275
;; flags: qr aa rd; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1
;; WARNING: recursion requested but not available

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 1232
; COOKIE: f41f6d773c0acfd0 (echoed)
;; QUESTION SECTION:
;extdns-coredns.extdns.svc.cluster.local. IN A

;; ANSWER SECTION:
extdns-coredns.extdns.svc.cluster.local. 5 IN A	192.168.49.99

;; Query time: 0 msec
;; SERVER: 192.168.49.99#53(192.168.49.99) (UDP)
;; WHEN: Sun May 17 18:46:18 BST 2026
;; MSG SIZE  rcvd: 135

make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
CoreDNS with k8s_external plugin is listening on: 192.168.49.99:53
CLUSTER_IP=
IP_PREFIX=
#@sudo --preserve-env=http_proxy --preserve-env=https_proxy sed -i.x -e '/DNS=/d' /etc/systemd/resolved.conf

; <<>> DiG 9.20.18-1ubuntu2-Ubuntu <<>> extdns-coredns.extdns.svc.cluster.local
;; global options: +cmd
;; Got answer:
;; WARNING: .local is reserved for Multicast DNS
;; You are currently testing what happens when an mDNS query is leaked to DNS
;; ->>HEADER<<- opcode: QUERY, status: NXDOMAIN, id: 37667
;; flags: qr rd ra; QUERY: 1, ANSWER: 0, AUTHORITY: 1, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 65494
;; QUESTION SECTION:
;extdns-coredns.extdns.svc.cluster.local. IN A

;; AUTHORITY SECTION:
.			3600	IN	SOA	a.root-servers.net. nstld.verisign-grs.com. 2026051700 1800 900 604800 86400

;; Query time: 28 msec
;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP)
;; WHEN: Sun May 17 18:46:19 BST 2026
;; MSG SIZE  rcvd: 143

You have disabled automatic update of the local DNS server.
Update your DNS to include nameserver: 192.168.49.99 and search domain: svc.cluster.local
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[2]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
# Now setup the Proxy to the NGINX Ingress and APIServer, and any NodePort services
# need to know the device and IP as this must go in the proxy config
Installing HAProxy frontend to make Minikube externally addressable
CLUSTER_IP: 192.168.49.2
Adding proxy for NodePort 80
Adding proxy for NodePort 443
462df713cfd577293a0c82c8299a965c1e37e7330fc960cb8cffe438e1589915
make[2]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[2]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Installing Docker Registry to integrate with Minikube
0de103ee93b44d754162f3e856dc844d1822c62610a8e0eeedf95db43fc99b20
make[2]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
make[1]: Entering directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'
Minikube Installed:        Yes!
Helm Installed:            Yes!
Profile:                   minikube
DRIVER:                    docker
RUNTIME:                   docker
HAPROXY_ENGINE:            docker
ADD_ARGS:                  
ADDONS:                    metrics-server csi-hostpath-driver volumesnapshots csi-hostpath-driver volumesnapshots
TOOLS:                     yes 
CILIUM:                    yes
CILIUM_VERSION:            v1.19.2
KYVERNO:                   no 
CPUS:                      8
MEM:                       16384
OS_NAME:                   linux
OS_ARCH:                   unknown
OS_BIN:                    amd64
EXE_DIR:                   /usr/local/bin
SUDO_FOR_EXE_DIR:          sudo --preserve-env=http_proxy --preserve-env=https_proxy
IPADDR:                    192.168.178.23
CLUSTER_IP:                192.168.49.2
HOSTNAME:                  wattle
CLUSTER_DOMAIN:            cluster.local
FQDN:                      wattle.local.net
MOUNT_FROM:                /srv
MOUNT_TO:                  /srv
PROXY_VERSION:             3.2.4
PROXY_CONFIG:              /home/piers/.minikube/minikube-nginx-haproxy.cfg
MINIKUBE_VERSION:          v1.38.1
MINIKUBE_NETWORK:          minikube
KUBERNETES_VERSION:        v1.35.3
KUBERNETES_SERVER_VERSION: v1.35.3
HELM_VERSION:              v3.20.1
HELMFILE_VERSION:          1.4.3
YQ_VERSION:                4.52.5
KYVERNO_VERSION:           1.17.2
CILIUM_CLI_VERSION:        0.19.2
INGRESS:                   http://192.168.49.2
USE_CACHE:                 yes
CACHE_DATA:                /home/piers/.minikube/registry_cache
KIND_VERSION:              v0.31.0
KIND_DRIVER:               docker
Minikube status:
minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

Cilium status:
    /¯¯\
 /¯¯\__/¯¯\    Cilium:             OK
 \__/¯¯\__/    Operator:           OK
 /¯¯\__/¯¯\    Envoy DaemonSet:    OK
 \__/¯¯\__/    Hubble Relay:       OK
    \__/       ClusterMesh:        disabled

DaemonSet              cilium                   Desired: 1, Ready: 1/1, Available: 1/1
DaemonSet              cilium-envoy             Desired: 1, Ready: 1/1, Available: 1/1
Deployment             cilium-operator          Desired: 1, Ready: 1/1, Available: 1/1
Deployment             hubble-relay             Desired: 1, Ready: 1/1, Available: 1/1
Deployment             hubble-ui                Desired: 1, Ready: 1/1, Available: 1/1
Containers:            cilium                   Running: 1
                       cilium-envoy             Running: 1
                       cilium-operator          Running: 1
                       clustermesh-apiserver    
                       hubble-relay             Running: 1
                       hubble-ui                Running: 1
Cluster Pods:          18/18 managed by Cilium
Helm chart version:    1.19.2
Image versions         cilium             quay.io/cilium/cilium:v1.19.2@sha256:7bc7e0be845cae0a70241e622cd03c3b169001c9383dd84329c59ca86a8b1341: 1
                       cilium-envoy       quay.io/cilium/cilium-envoy:v1.35.9-1773656288-7b052e66eb2cfc5ac130ce0a5be66202a10d83be@sha256:60031f39669542b21aedf05a3317d14e8d3ea48255790af039b315a1c9637361: 1
                       cilium-operator    quay.io/cilium/operator-generic:v1.19.2@sha256:e363f4f634c2a66a36e01618734ea17e7b541b949b9a5632f9c180ab16de23f0: 1
                       hubble-relay       quay.io/cilium/hubble-relay:v1.19.2@sha256:9987c73bad48c987fd065185535fd15a6717cbe8a8caf7fc7ef0413532cf490e: 1
                       hubble-ui          quay.io/cilium/hubble-ui-backend:v0.13.3@sha256:db1454e45dc39ca41fbf7cad31eec95d99e5b9949c39daaad0fa81ef29d56953: 1
                       hubble-ui          quay.io/cilium/hubble-ui:v0.13.3@sha256:661d5de7050182d495c6497ff0b007a7a1e379648e60830dd68c4d78ae21761d: 1
make[1]: Leaving directory '/home/piers/git/public/ska-telescope/sdi/ska-cicd-deploy-minikube'

This will install minikube, and optionally the haproxy if you are on Ubuntu.

Test the deployment

A basic functional test can be performed with the following make cluster-test. It will create a PersistentVolume, Deployments, an Ingress, and a LoadBalancer Service, and test connectivity using curl:

$ make cluster-test
export CLASS=nginx; \
bash ./scripts/test-ingress.sh
Check the Kubernetes cluster:
Connecting using KUBECONFIG=

Version Details:
Client Version: v1.35.3
Kustomize Version: v5.7.1
Server Version: v1.35.3

List nodes:
NAME       STATUS   ROLES           AGE    VERSION   INTERNAL-IP    EXTERNAL-IP   OS-IMAGE                         KERNEL-VERSION     CONTAINER-RUNTIME
minikube   Ready    control-plane   151m   v1.35.3   192.168.49.2   <none>        Debian GNU/Linux 12 (bookworm)   7.0.0-15-generic   docker://29.2.1

Check the Ingress connection details:
Ingress Controller LoadBalancer externalIP is: 192.168.49.2:30080


Show StorageClasses:
NAME                 PROVISIONER                RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
bds1                 hostpath.csi.k8s.io        Delete          Immediate           false                  150m
block                hostpath.csi.k8s.io        Delete          Immediate           false                  150m
csi-hostpath-sc      hostpath.csi.k8s.io        Delete          Immediate           false                  150m
nfs                  hostpath.csi.k8s.io        Delete          Immediate           false                  150m
nfss1                hostpath.csi.k8s.io        Delete          Immediate           false                  150m
standard (default)   k8s.io/minikube-hostpath   Delete          Immediate           false                  151m

Next: show StorageClass details.

Check Ingress Controller is ready:
deployment.apps/ingress-nginx-controller condition met

Deploy the Integration test:persistentvolume/pvtest1 created
persistentvolume/pvtest2 created
persistentvolumeclaim/pvc-test1 created
persistentvolumeclaim/pvc-test2 created
configmap/test created
service/nginx1 created
deployment.apps/nginx-deployment1 created
service/nginx2 created
deployment.apps/nginx-deployment2 created
ingress.networking.k8s.io/nginx1 created
ingress.networking.k8s.io/nginx2 created
service/cilium-nginx1 created
ingress.networking.k8s.io/cilium-nginx1 created
service/cilium-nginx2 created
ingress.networking.k8s.io/cilium-nginx2 created
httproute.gateway.networking.k8s.io/nginx1 created
httproute.gateway.networking.k8s.io/nginx2 created
ingress.networking.k8s.io/nginx2-oss created
ingress.networking.k8s.io/nginx2-haproxy created
NAME                                READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES       SELECTOR
deployment.apps/nginx-deployment1   0/3     3            0           0s    nginx        nginx:1.31   app=nginx1
deployment.apps/nginx-deployment2   0/1     1            0           0s    nginx        nginx:1.31   app=nginx2

NAME                                     READY   STATUS              RESTARTS   AGE   IP       NODE       NOMINATED NODE   READINESS GATES
pod/nginx-deployment1-546b49ffb8-47scn   0/1     ContainerCreating   0          0s    <none>   minikube   <none>           <none>
pod/nginx-deployment1-546b49ffb8-g9mhz   0/1     ContainerCreating   0          0s    <none>   minikube   <none>           <none>
pod/nginx-deployment1-546b49ffb8-n6tlj   0/1     ContainerCreating   0          0s    <none>   minikube   <none>           <none>
pod/nginx-deployment2-678b9f58d6-h8scp   0/1     Pending             0          0s    <none>   <none>     <none>           <none>

NAME                    TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE   SELECTOR
service/cilium-nginx1   ClusterIP   10.111.98.2      <none>        80/TCP    0s    app=nginx1
service/cilium-nginx2   ClusterIP   10.109.220.202   <none>        80/TCP    0s    app=nginx2
service/nginx1          ClusterIP   10.111.199.95    <none>        80/TCP    0s    app=nginx1
service/nginx2          ClusterIP   10.111.179.57    <none>        80/TCP    0s    app=nginx2

NAME                                       CLASS       HOSTS        ADDRESS         PORTS   AGE
ingress.networking.k8s.io/cilium-nginx1    cilium      *            192.168.49.96   80      0s
ingress.networking.k8s.io/cilium-nginx2    cilium      *            192.168.49.96   80      0s
ingress.networking.k8s.io/nginx1           nginx       *                            80      0s
ingress.networking.k8s.io/nginx2           nginx       *                            80      0s
ingress.networking.k8s.io/nginx2-haproxy   haproxy     *                            80      0s
ingress.networking.k8s.io/nginx2-oss       nginx-oss   *.skao.int                   80      0s

NAME                                         HOSTNAMES   AGE
httproute.gateway.networking.k8s.io/nginx1               0s
httproute.gateway.networking.k8s.io/nginx2               0s

Next: Check deployment.
Waiting for resources to deploy...
deployment.apps/nginx-deployment1 condition met
deployment.apps/nginx-deployment2 condition met
service/nginx-deployment1 exposed
NAME                                READY   UP-TO-DATE   AVAILABLE   AGE   CONTAINERS   IMAGES       SELECTOR
deployment.apps/nginx-deployment1   3/3     3            3           4s    nginx        nginx:1.31   app=nginx1
deployment.apps/nginx-deployment2   1/1     1            1           4s    nginx        nginx:1.31   app=nginx2

NAME                                     READY   STATUS    RESTARTS   AGE   IP           NODE       NOMINATED NODE   READINESS GATES
pod/nginx-deployment1-546b49ffb8-47scn   1/1     Running   0          4s    10.0.0.138   minikube   <none>           <none>
pod/nginx-deployment1-546b49ffb8-g9mhz   1/1     Running   0          4s    10.0.0.40    minikube   <none>           <none>
pod/nginx-deployment1-546b49ffb8-n6tlj   1/1     Running   0          4s    10.0.0.82    minikube   <none>           <none>
pod/nginx-deployment2-678b9f58d6-h8scp   1/1     Running   0          4s    10.0.0.79    minikube   <none>           <none>

NAME                        TYPE           CLUSTER-IP       EXTERNAL-IP      PORT(S)        AGE   SELECTOR
service/cilium-nginx1       ClusterIP      10.111.98.2      <none>           80/TCP         4s    app=nginx1
service/cilium-nginx2       ClusterIP      10.109.220.202   <none>           80/TCP         4s    app=nginx2
service/nginx-deployment1   LoadBalancer   10.109.245.97    192.168.49.100   80:30995/TCP   0s    app=nginx1
service/nginx1              ClusterIP      10.111.199.95    <none>           80/TCP         4s    app=nginx1
service/nginx2              ClusterIP      10.111.179.57    <none>           80/TCP         4s    app=nginx2

NAME                                       CLASS       HOSTS        ADDRESS         PORTS   AGE
ingress.networking.k8s.io/cilium-nginx1    cilium      *            192.168.49.96   80      4s
ingress.networking.k8s.io/cilium-nginx2    cilium      *            192.168.49.96   80      4s
ingress.networking.k8s.io/nginx1           nginx       *                            80      4s
ingress.networking.k8s.io/nginx2           nginx       *                            80      4s
ingress.networking.k8s.io/nginx2-haproxy   haproxy     *            192.168.49.98   80      4s
ingress.networking.k8s.io/nginx2-oss       nginx-oss   *.skao.int   192.168.49.97   80      4s

Next: perform write/read test.
Perform write and then read test to/from shared storage (1) - expected date stamp: Mon 18 May 07:34:44 BST 2026

echo "echo 'Mon 18 May 07:34:44 BST 2026' > /usr/share/nginx/html/index.html" | kubectl -n ${NAMESPACE} exec -i $(kubectl get pods -l app=nginx1 -o name | head -1) -- bash

Waiting for LoadBalancer ...
Waiting for external IP
Found external IP: 192.168.49.100

Test Ingress -> Deployment: nginx1
----------------------------------------nginx1----------------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.2:30080/nginx1/
curl Ingress for nginx1 rc: 0
Received: Mon 18 May 07:34:44 BST 2026 == Mon 18 May 07:34:44 BST 2026 - OK
Perform write and then read test to/from shared storage (2) - expected date stamp: Mon 18 May 07:34:50 BST 2026

echo "echo 'Mon 18 May 07:34:50 BST 2026' > /usr/share/nginx/html/index.html" | kubectl -n ${NAMESPACE} exec -i $(kubectl get pods -l app=nginx2 -o name | head -1) -- bash


Test Ingress -> Deployment: nginx2
----------------------------------------nginx2----------------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.2:30080/nginx2/
curl Ingress for nginx2 rc: 0
Received: Mon 18 May 07:34:50 BST 2026 == Mon 18 May 07:34:50 BST 2026 - OK


Test Nginx Ingress Controller -> Deployment: nginx2
----------------------------------------nginx2----------------------------------------
no_proxy=192.168.49.2,localhost curl -s -H 'Host: test.skao.int' http://192.168.49.97/nginx2/
curl Ingress for nginx2 rc: 0
Received: Mon 18 May 07:34:50 BST 2026 == Mon 18 May 07:34:50 BST 2026 - OK


Test HAProxy Ingress Controller -> Deployment: nginx2
----------------------------------------nginx2----------------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.98/nginx2/
curl Ingress for nginx2 rc: 0
Received: Mon 18 May 07:34:50 BST 2026 == Mon 18 May 07:34:50 BST 2026 - OK


Test metallb LoadBalancer
----------------------------------nginx-deployment1-----------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.100/
curl LoadBalancer rc: 0
Received: Mon 18 May 07:34:44 BST 2026 == Mon 18 May 07:34:44 BST 2026 - OK


Test Cilium Ingress Controller
----------------------------------nginx-deployment1-----------------------------------
minikube ssh "curl -s http://192.168.49.96/nginx1/"
res=Mon 18 May 07:34:44 BST 2026
curl Cilium LB rc: 0
Received: Mon 18 May 07:34:44 BST 2026 == Mon 18 May 07:34:44 BST 2026 - OK

----------------------------------nginx-deployment2-----------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.96/nginx2/
curl Cilium LB rc: 0
Received: Mon 18 May 07:34:50 BST 2026 == Mon 18 May 07:34:50 BST 2026 - OK


Test Gateway API
----------------------------------nginx-deployment1-----------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.95/nginx1/
curl httproute rc: 0
Received: Mon 18 May 07:34:44 BST 2026 == Mon 18 May 07:34:44 BST 2026 - OK

----------------------------------nginx-deployment2-----------------------------------
no_proxy=192.168.49.2,localhost curl -s http://192.168.49.95/nginx2/
curl httproute rc: 0
Received: Mon 18 May 07:34:50 BST 2026 == Mon 18 May 07:34:50 BST 2026 - OK

Cleanup resources
httproute.gateway.networking.k8s.io "nginx1" deleted from default namespace
httproute.gateway.networking.k8s.io "nginx2" deleted from default namespace
ingress.networking.k8s.io "nginx1" deleted from default namespace
ingress.networking.k8s.io "nginx2" deleted from default namespace
ingress.networking.k8s.io "cilium-nginx1" deleted from default namespace
ingress.networking.k8s.io "cilium-nginx2" deleted from default namespace
ingress.networking.k8s.io "nginx2-oss" deleted from default namespace
ingress.networking.k8s.io "nginx2-haproxy" deleted from default namespace
service "nginx-deployment1" deleted from default namespace
service "nginx1" deleted from default namespace
service "cilium-nginx1" deleted from default namespace
deployment.apps "nginx-deployment1" deleted from default namespace
service "nginx2" deleted from default namespace
service "cilium-nginx2" deleted from default namespace
deployment.apps "nginx-deployment2" deleted from default namespace
persistentvolumeclaim "pvc-test1" deleted from default namespace
Warning: deleting cluster-scoped resources, not scoped to the provided namespace
persistentvolume "pvtest1" deleted
persistentvolumeclaim "pvc-test2" deleted from default namespace
persistentvolume "pvtest2" deleted
configmap "test" deleted from default namespace
Overall exit code is: 0

This will deploy some NGINX webservers, and then test accessing them through the Ingress Controller.

Preload Images from a Helm Chart

In order to speed up your deployments in Minikube, it is possible to preload the images. The following shows two ways of loading images from Helm Charts.

From a Central Artefact Repository Chart

Run the following make target to introspect a Helm Chart from the SKAO Central Artefact Repository, and load the images therein:

$ make minikube-load-images K8S_CHARTS=ska-tango-base
export K8S_CHART_PARAMS=; \
bash ./scripts/load-images.sh "ska-tango-base"
Searching in charts: ska-tango-base
Checking chart: ska-tango-base
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/databaseds.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/tangodb.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/databaseds.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/tangodb.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/ingress.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
wrote /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml

looking for images in: /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/databaseds.yaml
looking for images in: /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/deviceservers.yaml
looking for images in: /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/ingress.yaml
looking for images in: /tmp/chart-ska-tango-base.oMYhEAaCxJ/ska-tango-base/templates/tangodb.yaml
Combined list of charts to load:
artefact.skao.int/ska-tango-images-tango-cpp:9.3.9
artefact.skao.int/ska-tango-images-tango-db:10.4.14
artefact.skao.int/ska-tango-images-tango-dsconfig:1.5.3
artefact.skao.int/ska-tango-images-tango-java:9.3.6

Finished searching charts, now loading images
loading image: artefact.skao.int/ska-tango-images-tango-cpp:9.3.9
loading image: artefact.skao.int/ska-tango-images-tango-db:10.4.14
loading image: artefact.skao.int/ska-tango-images-tango-dsconfig:1.5.3
loading image: artefact.skao.int/ska-tango-images-tango-java:9.3.6

List of loaded images:
k8s.gcr.io/pause:3.5
k8s.gcr.io/metrics-server/metrics-server:<none>
k8s.gcr.io/kube-scheduler:v1.22.3
k8s.gcr.io/kube-proxy:v1.22.3
k8s.gcr.io/kube-controller-manager:v1.22.3
k8s.gcr.io/kube-apiserver:v1.22.3
k8s.gcr.io/ingress-nginx/kube-webhook-certgen:<none>
k8s.gcr.io/ingress-nginx/controller:<none>
k8s.gcr.io/etcd:3.5.0-0
k8s.gcr.io/coredns/coredns:v1.8.4
gcr.io/k8s-minikube/storage-provisioner:v5
docker.io/metallb/speaker:<none>
docker.io/metallb/controller:<none>
docker.io/library/busybox:1.28.3
docker.io/kubernetesui/metrics-scraper:v1.0.7
docker.io/kubernetesui/dashboard:v2.3.1
docker.io/ivans3/minikube-log-viewer:<none>
artefact.skao.int/ska-tango-images-tango-rest:1.14.6
artefact.skao.int/ska-tango-images-tango-java:9.3.6
artefact.skao.int/ska-tango-images-tango-java:9.3.5
artefact.skao.int/ska-tango-images-tango-dsconfig:1.5.3
artefact.skao.int/ska-tango-images-tango-dsconfig:1.5.2
artefact.skao.int/ska-tango-images-tango-dsconfig:1.5.1
artefact.skao.int/ska-tango-images-tango-db:10.4.14
artefact.skao.int/ska-tango-images-tango-db:10.4.13
artefact.skao.int/ska-tango-images-tango-cpp:9.3.9
artefact.skao.int/ska-tango-images-tango-cpp:9.3.7
artefact.skao.int/ska-tango-examples:0.4.15
artefact.skao.int/ska-ser-skallop:2.7.4

To force reload an image use: minikube image load <image name>:<tag>

From a local directory

The same make target can be supplied with a local Helm Chart directory as the soruce and will attempt the same introspection to discover images to load:

$ make minikube-load-images K8S_CHARTS=../../ska-skampi/charts/ska-mid/

Because this process uses the helm template command to generate the templates to parse, it maybe necessary to pass in values in order to get the charts to render correctly. Additional command line arguments can be passed in using the K8S_CHART_PARAMS make variable.

Clean up again

Tear everything down again with:

$ make clean
✋  Stopping node "minikube"  ...
🛑  Powering off "minikube" via SSH ...
✋  Stopping node "minikube"  ...
🛑  Powering off "minikube" via SSH ...
✋  Stopping node "minikube"  ...
🛑  Powering off "minikube" via SSH ...
🛑  1 nodes stopped.
🔥  Deleting "minikube" in podman ...
🔥  Deleting container "minikube" ...
🔥  Removing /home/piers/.minikube/machines/minikube ...
💀  Removed all traces of the "minikube" cluster.

Custom Addons

Custom addons are additional make targets that add functionality or provide examples to augment the core cluster deployment on Minikube. These addons are found in the scripts directory in Makefiles ending in .mk.

Addon - Vault integration

The Vault Dev Server can be deployed, integrated with Kubenetes with make vault-install, after make all has been run deploying the core minikube cluster. This provides the Agent Sidecar Injector and the Vault CSI Provider out of the box.

Note: you must run make vault-setup to install the various Vault commandine applications first - this will happen automatically if you run make vault-install before any of the following.

Explore the Vault UI with make vault-ui - the default root VAULT_TOKEN is root. See example apps with make vault-example-apps, and examples of Environment variable and templating control with make vault-config-template and make vault-envconsul-test.

Using the tool medusa, the make target vault-import can be used to replicate data from the central SKAO Vault service to this local Vault Dev Server, eg: to replicate the /dev remote mount to local -

$ make vault-import VAULT_PATH=dev VAULT_EXPORT_PATH=/dev
Enter VAULT_TOKEN for https://vault.skao.int:
hvs.your.token.copied.from.browser
Secret successfully written to Vault [http://192.168.49.2:30820] using path [/mid-itf/eda]
$

Vault Targets and Vars

$ make help | grep -i vault
...
# installed Vault command line version
VAULT_VERSION                  1.15.4## Vault version to install https://releases.hashicorp.com/vault/
...
# Vault make targets
SECTION: scripts/vault
vault-config-template          Example of consul-template integrated with vault
vault-deploy                   Deploy integrated Vault server with injector and CSI support
vault-engines                  Setup a default set of Vault engines
vault-envconsul-test           Example of envconsul integrated with vault
vault-example-apps             Example of Vault injector and CSI applications
vault-export                   Export a given VAULT_EXPORT_PATH from vault.skao.int
vault-import                   Export a given VAULT_EXPORT_PATH from vault.skao.int and import to dev server at VAULT_PATH
vault-install                  Full end to end Vault install and integration
vault-k8s-integration          Integrate Vault with Kubernetes
vault-kvput                    kvput Vault secrets
vault-port-forward             Port forward the Vault API to localhost:8200
vault-port-forward-stop        Kill and existing Vault port forward
vault-setup                    install commandline apps for Vault
vault-ui                       Launch the browser to the Vault UI exposed on NodePort 30820
...
# Vault VARS for controlling install and behaviour
VAULT_AUTH_NAMESPACE           default## Namespace for Vault auth integration
VAULT_DEFAULT_AUTH             kubernetes## Vault auth method name
VAULT_DEFAULT_MOUNT            dev## default mount point
VAULT_DEFAULT_ROLE             kube-role## default Vault role
VAULT_DEV_SERVER_TOKEN         root## Root auth token for dev Vault instance
VAULT_ENGINE                   kv-v2## Default Vault engine kv version 2
VAULT_ENGINES                  kv dev mid-itf low-itf secret ## Vault kv engines to initialise
VAULT_EXPORT_PATH              /kv/users/$(VAULT_USER)## Export path from vault.skao.int - defaults to /kv/users/<VAULT_USER>
VAULT_FIELD                    testvalue## Vault fieldname for kvput
VAULT_K8S_ISSUER               https://kubernetes.default.svc.cluster.local## Certificate issue and API endpoint
VAULT_KVPATH                   config## Vault path added to VAULT_MOUNT for kvput
VAULT_MAX_VERSIONS             10000 ## Default maximum number of versions to retain for a secret
VAULT_MOUNT                    dev## Vault mount for kvput
VAULT_NAMESPACE                vault## Vault namespace for installation
VAULT_PATH                     kv/## Default Vault path
VAULT_SA                       vault-auth## Service account Name for Vault
VAULT_USER                     piersharding## vault.skao.int user account name for personal secrets
VAULT_VALUE                    $(VAULT_FIELD)=Wahoooo## Vault fieldname=value for kvput
...

Addon - Flux CD

The Flux CD Operator can be deployed, integrated with Kubenetes with make flux-install, after make all has been run deploying the core minikube cluster.

Note: you must run make flux-setup to install the Flux CD commandine application.

Flux Targets and Vars

$ make help | grep -i flux
...
SECTION: scripts/flux
flux-all                       build minikube and north, deploy fluxcd and run local and remote example
flux-clean                     Clean up after Flux demonstration
flux-examples-remote           Deploy remote full example of Tango in North
flux-install                   Install Flux CD in Minikube
flux-setup                     Install Flux CD commandline
flux-test-local                Deploy simple local test
flux-test-remote               Deploy simple remote test in North
FLUX_VERSION                   2.3.0## Flux CD tool version to install https://github.com/fluxcd/flux2/releases
...

Addon - Multicluster

Multicluster is a demo of howto use Cilium to create a zero trust framework for connecting Kubernetes clusters together and also off cluster workloads. A complete demo can be run with make multicluster-full-demo. Clean everything down again with make multicluster-clean.

Multicluster Targets and Vars

$ make help | grep -i multicluster
...
SECTION: scripts/multicluster
multicluster                   build north and south
multicluster-clean             Clean up after Flux demonstration
multicluster-clean-vm          Remove a kicbase container that emulates a VM
multicluster-configure-mesh    Configure cluster mesh
multicluster-configure-vm      Configure external workload VM
multicluster-create-vm         Create a kicbase container to emulate a VM
multicluster-demo              Run demo with shadow service in North pointing to South
multicluster-demo-south-external Run demo with external workload pointing to South
multicluster-load-image-to-vm  preload local cached cilium image for speed
multicluster-test              test north and south
multicluster-vars              MEM=4096 CPUS=4 CILIUM=yes KYVERNO=no SKA_TANGO_OPERATOR_ENABLED=false TOOLS=no
MULTICLUSTER_VM                cew
MULTICLUSTER_VM_IMAGE          gcr.io/k8s-minikube/kicbase:v0.0.50
...

Addon - Kueue

Kueue is a demo of howto use Kueue to create controlled group queue workloads. A complete demo can be run with make kueue-clean && make kueue-all &&  gnome-terminal --window -x bash -c "k9s --context minikube -A -c pods". Clean everything down again with make kueue-clean.

Kueue Targets and Vars

$ make help | grep -i kueue
SECTION: scripts/kueue
kueue-all                      build minikube , deploy fluxcd and run local example
kueue-clean                    Clean up after Flux demonstration
kueue-examples                 Deploy kueue examples
kueue-install                  Install Kueue in Minikube
kueue-install-prom             Install Prom Stack in Minikube
kueue-setup                    install kueue commandline
kueue-viz-frontend             install kueue-viz backend - it's experimental!!!
kueue-viz                      install kueue-viz backend - it's experimental!!!
KUEUE_PROM_STACK_VERSION       67.4.0## kube-prometheus-stack version to install https://github.com/prometheus-community/helm-charts/releases
KUEUE_SKA_TANGO_OPERATOR_ENABLED false##decide whether or not to deploy tango operator for Kueue
KUEUE_VERSION                  v0.10.0## Kueue version to install https://github.com/kubernetes-sigs/kueue/releases

Notes

  • make minikube-haproxy adds in a proxy for all NodePort address in the cluster - if you add a new service that requires exposing, then just rerun make minikube-haproxy. This only works on Ubuntu as it requires podman.

  • http_proxy, https_proxy, and no_proxy will be passed through to minikube start if set, on make minikube-install.

  • Configuration of additional --apiserver-names and --apiserver-ips are passed through to minikube start, on make minikube-install so that Kubernetes APIServer can be addressed remotely through the HAProxy.

  • MOUNT_FROM and MOUNT_TO are passed to minikube start, on make minikube-install for --mount-string so that a user supplied directory is mounted into the Kubernetes cluster and available for mounting in Pods.

Using A Proxy

When you must use a proxy to reach the outside world then the configuration must be set in two places:

  • Configure the dockerd to use the proxy - https://docs.docker.com/config/daemon/systemd/#httphttps-proxy

  • Set the environment variables in your shell - typically set the following values in ~/.bashrc :

export HTTP_PROXY=http://my.proxy.server:8888
export HTTPS_PROXY=http://my.proxy.server:8888
export NO_PROXY="202.9.15.208,localhost,127.0.0.1,10.96.0.0/12,192.168.99.0/24,192.168.39.0/24,172.17.0.1/16"

export http_proxy=http://my.proxy.server:8888
export https_proxy=http://my.proxy.server:8888
export no_proxy="202.9.15.208,localhost,127.0.0.1,10.96.0.0/12,192.168.99.0/24,192.168.39.0/24,172.17.0.1/16"

podman will honour the above environment variables.

Adjust the above settings according to your environment. Preserve the Kubernetes and Docker specific values for 10.96.0.0/12 and 172.17.0.1/16. Check here for updates https://minikube.sigs.k8s.io/docs/handbook/vpn_and_proxy/ .

Using A Docker Image Proxy/Cache

:zap: only on Ubuntu.

If you are not already using a (possibly corporate) proxy, then it is possible to setup your own personal pull-through Docker Image Proxy for Minikube using https://github.com/rpardini/docker-registry-proxy . This will create a local cache of images that are pulled so that the second time you make a deployment in Minikube, the cache will respond without going to the upstream image registry. This is currently configured to cache:

  • docker.io

  • gcr.io

  • k8s.gcr.io

  • quay.io

  • registry.k8s.io

  • registry.gitlab.com

  • docker.elastic.co

This will help work around pull throttling introduced by Docker Hub (https://docs.docker.com/docker-hub/download-rate-limit/), but will also speed up your deployments, as the cache can be maintained between re/installs of Minikube.

Deploy the cache using:

$ make all USE_CACHE=yes

Running make minikube-clean (when you teardown Minikube - alias clean) will not clean out the cache. If you want to remove the cached images altogether then you must uninstall Minikube and the clean the cache with:

$ make minikube-clean
$ make minikube-clean-cache

Using NGiNX

NGiNX is now deployed by default following the removal of Traefik as an ingress controller from the SKA cluster.

Caveats

Encryption

If your base OS is using an Encrypted Filesystem - by either checking the full disk encryption option on Ubuntu Installation, or by using a Home Folder encryption on one of its flavours - this repository will not work for you.

The filesystem overlayfs can’t work on top of encryptfs, will fail to start the minikube VM and potentially can lead to data loss on your encrypted filesystem.

As a possible work around, you can try using the qemu driver with:

make all DRIVER=qemu

OS Variations

Ubuntu

  • docker-ce or docker.io installed and the current user in the docker group

  • /srv directory must exist: sudo mkdir -p /srv

  • make, curl, unzip, git

:zap: Make sure that you have passwordless sudo setup - see https://serverfault.com/questions/160581/how-to-setup-passwordless-sudo-on-linux.

export ACCOUNT=<your account name here>
echo "${ACCOUNT} ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/${ACCOUNT}
chmod 440 /etc/sudoers.d/${ACCOUNT}

macOS

MacOS cannot run containers natively, so requires a virtualisation layer. The Tried and tested approach is to use a Qemu based VM, which is done by default with setting DRIVER=qemu and RUNTIME=docker when MacOS is detected.

First install Xcode command line tools:

xcode-select --install

Please install jq as this is required for output parsing:

brew install jq

Also macOS does not have envsubst by default. This can be installed by:

brew install gettext

Install IP tools to help debug things:

brew install iproute2mac

Install GNU Make and make it default by following the documentation outputted by brew at the end of installation to ensure that it is found first in your PATH:

brew install make

Install GNU Sed and make it default by following the documentation outputted by brew at the end of installation to ensure that it is found first in your PATH:

brew install gnu-sed

Note - do not use Docker Desktop - it seems to have a brittle integration with Minikue. If you insist on it then, to install Docker Desktop on MacOS:

brew install --cask docker

:zap: If you are using macOS M2 arm64, then the last known working combination is the Qemu driver with Kubernetes 1.35.3 on Tahoe 26.4.1

First, follow the instructions for installing qemu support from here: https://minikube.sigs.k8s.io/docs/drivers/qemu/ Install qemu with:

brew install qemu
brew install libvirt
brew install socket_vmnet
HOMEBREW=$(which brew) && sudo ${HOMEBREW} services restart socket_vmnet

To deploy Minikube use:

make all CPUS=4 MEM=8092

WSL2 (Ubuntu 22.04 / 24.04)

Before installing minikube using this repository you will need to

  • WSL2 enabled with an Ubuntu distribution

  • docker-ce installed natively inside Ubuntu (not the Docker Desktop WSL backend)(see instructions here

  • The current user in the docker group: sudo usermod -aG docker $USER

  • make, curl, unzip, git

  • run systemctl faker script or add into the local file .profile the command: wsl.exe -u root -e sh -c "service docker status || service docker start

  • windows terminal preview is also highly recommended!

Steps:

# install windows docker-ce
# check docker is available under ubuntu
docker version
# get systemd enabler
git clone https://github.com/alfink/ubuntu-wsl2-systemd-script
cd ubuntu-wsl2-systemd-script
bash ubuntu-wsl2-systemd-script.sh
# or change the .profile file
echo "wsl.exe -u root -e sh -c "service docker status || service docker start" >> .profile
# start new wsl2 terminal - you should see a message about systemctl
# clone this repo and install minikube
git clone https://gitlab.com/ska-telescope/sdi/cka-cicd-deploy-minikube.git
# Follow the above steps as a normal Ubuntu installation, configure the variables as you like
# ### IMPORTANT use docker driver not non as states in "official" blog post

In order to access the ingress on minikube, please note that the docker internal ip address is not reachable from windows host. Instead of using the minikube ip, please use the WSL2 ip address which can be found using the following command:

hostname -I | awk '{print $1}'

For ska-cicd-deploy-minikube Developers

Currently, it is not possible to run the full test suite for ska-cicd-deploy-minikube in the pipeline because it requires deployment within a VM (not container in container). This means that developers should run the make bats-test test suite locally before pushing commits to ensure the wider functionality is tested.

A pre-push git hook that will remind you to do the testing can be activated with:

$ git config --local core.hooksPath  resources/git-hooks/