Minikube Add-ons for Production-Like Environments#

A bare minikube cluster runs workloads but lacks the infrastructure that production clusters rely on – metrics collection, ingress routing, TLS, monitoring, and load balancer support. Minikube’s addon system bridges this gap with one-command installs of production components.

Surveying Available Add-ons#

List everything minikube offers:

minikube addons list

This prints dozens of addons with their status. Most are disabled by default. The ones worth enabling depend on what you are testing, but a production-like setup typically needs five to seven of them.

Essential Add-ons#

metrics-server#

Enables kubectl top commands and is required for HorizontalPodAutoscaler to function.

minikube addons enable metrics-server

Verify it is working:

kubectl top nodes
# NAME       CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%
# minikube   250m         6%     1024Mi           25%

kubectl top pods -A

Resource footprint is minimal – under 50MB of memory. Enable this in every minikube cluster.

ingress#

Deploys an nginx ingress controller, letting you create Ingress resources just like in production.

minikube addons enable ingress

Create an Ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: myapp-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: myapp.local
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myapp
                port:
                  number: 80

To reach the ingress from your host, get the minikube IP and add it to /etc/hosts:

echo "$(minikube ip) myapp.local" | sudo tee -a /etc/hosts

On Docker driver setups (common on macOS), you need minikube tunnel running in a separate terminal to expose the ingress controller’s LoadBalancer service.

ingress-dns#

Automates DNS resolution for ingress hostnames so you do not have to manually edit /etc/hosts:

minikube addons enable ingress-dns

After configuration, *.test domains resolve to the minikube IP automatically. Follow the minikube docs for the one-time resolver setup on your OS.

dashboard#

The Kubernetes Dashboard UI for visual cluster inspection:

minikube addons enable dashboard
minikube dashboard

This opens the dashboard in your browser. Useful for quickly inspecting workloads, but not something you need running at all times.

registry#

Runs a container registry inside minikube at localhost:5000. Push images to it and reference them in deployments without configuring imagePullSecrets:

minikube addons enable registry

Push an image:

docker tag myapp:latest localhost:5000/myapp:latest
docker push localhost:5000/myapp:latest

Reference it in a deployment:

containers:
  - name: myapp
    image: localhost:5000/myapp:latest

On macOS with the Docker driver, you need to set up port forwarding for the registry. Run this in the background:

kubectl port-forward -n kube-system service/registry 5000:80 &

The registry addon is lightweight (around 30MB memory) and eliminates the need for Docker Hub or any external registry during development.

metallb#

Provides LoadBalancer service support. Without it, services of type LoadBalancer stay in Pending state forever in minikube.

minikube addons enable metallb

Configure an IP range for metallb to assign from:

minikube addons configure metallb
# -- Enter Load Balancer Start IP: 192.168.49.100
# -- Enter Load Balancer End IP: 192.168.49.110

The IP range should be within minikube’s network. Check your minikube subnet:

minikube ip
# 192.168.49.2

Pick a range in the same /24 that does not conflict with the node IP. Once configured, LoadBalancer services get real IPs:

kubectl get svc
# NAME    TYPE           CLUSTER-IP      EXTERNAL-IP      PORT(S)
# myapp   LoadBalancer   10.96.123.45    192.168.49.100   80:31234/TCP

Monitoring Stack via Helm#

Minikube does not have a built-in monitoring addon, but you can install the kube-prometheus-stack via Helm. This gives you Prometheus, Grafana, and Alertmanager in one chart.

helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update

helm install monitoring prometheus-community/kube-prometheus-stack \
  --namespace monitoring \
  --create-namespace \
  --set prometheus.prometheusSpec.resources.requests.memory=512Mi \
  --set prometheus.prometheusSpec.resources.requests.cpu=250m \
  --set grafana.resources.requests.memory=256Mi \
  --set alertmanager.alertmanagerSpec.resources.requests.memory=128Mi

Access Grafana:

kubectl port-forward -n monitoring svc/monitoring-grafana 3000:80
# Default credentials: admin / prom-operator

This stack needs at least 2GB of available memory in minikube. Start minikube with adequate resources:

minikube start --cpus=4 --memory=8192

cert-manager for TLS Testing#

Install cert-manager via Helm to test TLS certificate workflows:

helm repo add jetstack https://charts.jetstack.io
helm repo update

helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set crds.enabled=true

Create a self-signed ClusterIssuer for local testing:

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: selfsigned-issuer
spec:
  selfSigned: {}
---
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: myapp-tls
  namespace: default
spec:
  secretName: myapp-tls-secret
  issuerRef:
    name: selfsigned-issuer
    kind: ClusterIssuer
  dnsNames:
    - myapp.local
    - myapp.test

This creates a TLS secret that you can reference in Ingress resources, testing the same certificate workflow you would use in production with Let’s Encrypt or an internal CA.

Resource Impact of Add-ons#

Not all addons are equal in resource consumption:

Add-on Memory CPU Notes
metrics-server ~40MB Minimal Enable always
ingress (nginx) ~100MB Minimal Enable when testing HTTP routing
dashboard ~200MB Low Enable on demand
registry ~30MB Minimal Enable for image workflow testing
metallb ~50MB Minimal Enable when you need LoadBalancer IPs
kube-prometheus-stack ~2GB+ Moderate Enable only when testing monitoring
cert-manager ~100MB Low Enable when testing TLS

Plan your minikube memory allocation accordingly. A cluster with metrics-server, ingress, registry, and metallb needs roughly 4GB total (including system components). Add the monitoring stack and you need 6-8GB.

Practical Setup Script#

A bash script that creates a production-like minikube environment:

#!/usr/bin/env bash
set -euo pipefail

CLUSTER_NAME="${1:-dev}"
CPUS="${2:-4}"
MEMORY="${3:-8192}"
K8S_VERSION="${4:-v1.29.0}"

echo "Starting minikube cluster: ${CLUSTER_NAME}"
minikube start \
  -p "${CLUSTER_NAME}" \
  --driver=docker \
  --cpus="${CPUS}" \
  --memory="${MEMORY}" \
  --kubernetes-version="${K8S_VERSION}"

echo "Enabling core addons..."
minikube -p "${CLUSTER_NAME}" addons enable metrics-server
minikube -p "${CLUSTER_NAME}" addons enable ingress
minikube -p "${CLUSTER_NAME}" addons enable registry
minikube -p "${CLUSTER_NAME}" addons enable dashboard

echo "Configuring metallb..."
minikube -p "${CLUSTER_NAME}" addons enable metallb
MINIKUBE_IP=$(minikube -p "${CLUSTER_NAME}" ip)
IP_PREFIX=$(echo "${MINIKUBE_IP}" | cut -d. -f1-3)
cat <<EOF | minikube -p "${CLUSTER_NAME}" kubectl -- apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - ${IP_PREFIX}.100-${IP_PREFIX}.110
EOF

echo "Installing cert-manager..."
helm repo add jetstack https://charts.jetstack.io --force-update
helm install cert-manager jetstack/cert-manager \
  --namespace cert-manager \
  --create-namespace \
  --set crds.enabled=true \
  --kube-context "${CLUSTER_NAME}"

echo "Cluster ${CLUSTER_NAME} is ready with production-like addons."
kubectl --context "${CLUSTER_NAME}" get nodes

Run it with defaults or override:

chmod +x setup-minikube.sh
./setup-minikube.sh dev 4 8192 v1.29.0

This gives you a repeatable, production-like local cluster in under two minutes.