Skip to content

Testing Kubernetes Applications — Minikube, Kind & K3s Guide

DodaTech Updated 2026-06-24 4 min read

Testing Kubernetes applications requires validating that your deployments, services, and configurations work correctly against a real cluster before reaching production. In this guide, you will learn how to use Kind and Minikube for local testing, write integration tests that run against ephemeral clusters, and validate resource definitions with conformance testing tools. The DodaTech infrastructure team uses Kind clusters in CI to validate every manifest change for Doda Browser's backend services before deploying to production EKS.

Learning Path

flowchart LR
  A[Docker Containers] --> B[Kubernetes Basics]
  B --> C[Testing K8s Apps
You are here] C --> D[Service Mesh Testing] D --> E[Production Deployments] style C fill:#f90,color:#fff

Local Kubernetes Testing Options

Tool Startup Use Case
Minikube 2–5 min Full VM-based cluster with addons
Kind 30–60s Lightweight, ideal for CI
K3s 10–20s Minimal resource edge cluster
MicroK8s 30–60s Snap-based single-node cluster

Validating Kubernetes Manifests

Before deploying, validate your YAML files are syntactically correct:

# Dry-run validation
kubectl apply --dry-run=client -f deployment.yaml

# Schema validation with kubeconform
kubeconform -summary deployment.yaml

# Linting with kube-linter
kube-linter lint deployment.yaml

Expected output:

kubeconform: deployment.yaml - PASS
kube-linter: no lint errors found

Integration Testing with Kind

Kind runs Kubernetes clusters in Docker containers, perfect for CI:

import subprocess, json, time, requests

def create_kind_cluster(name="test-cluster"):
    subprocess.run(["kind", "create", "cluster", "--name", name], check=True)
    print(f"Cluster {name} created")

def deploy_app():
    subprocess.run(["kubectl", "apply", "-f", "deployment.yaml"], check=True)
    subprocess.run(["kubectl", "apply", "-f", "service.yaml"], check=True)
    subprocess.run(["kubectl", "rollout", "status", "deployment/myapp", "--timeout=60s"], check=True)
    print("App deployed successfully")

def wait_for_service(name="myapp-service", namespace="default", timeout=60):
    start = time.time()
    while time.time() - start < timeout:
        result = subprocess.run([
            "kubectl", "get", "service", name,
            "-n", namespace, "-o", "json]
        ], capture_output=True, text=True)
        svc = json.loads(result.stdout)
        if svc.get("status", {}).get("loadBalancer", {}).get("ingress"):
            return svc["status"]["loadBalancer"]["ingress"][0]
        time.sleep(2)
    return None

def test_service():
    create_kind_cluster()
    deploy_app()
    endpoint = wait_for_service()
    if endpoint:
        r = requests.get(f"http://{endpoint['ip']}:8080/health")
        assert r.status_code == 200
        print("Service health check passed")
    subprocess.run(["kind", "delete", "cluster", "--name", "test-cluster"])

test_service()

Testing ConfigMaps and Secrets

import subprocess, yaml

def test_configmap():
    result = subprocess.run(
        ["kubectl", "get", "configmap", "app-config", "-o", "yaml"],
        capture_output=True, text=True
    )
    config = yaml.safe_load(result.stdout)
    data = config["data"]
    assert data["LOG_LEVEL"] == "debug"
    assert "DATABASE_URL" in data
    print("ConfigMap validation passed")

def test_secret_mounts():
    result = subprocess.run(
        ["kubectl", "get", "pod", "-l", "app=myapp", "-o", "json"],
        capture_output=True, text=True
    )
    pods = json.loads(result.stdout)
    for pod in pods["items"]:
        volumes = pod["spec"]["volumes"]
        has_secret = any(v.get("secret") for v in volumes)
        assert has_secret, f"Pod {pod['metadata']['name']} missing secret volume"
    print("Secret mount validation passed")

test_configmap()
test_secret_mounts()

Testing Network Policies

import subprocess

def test_network_isolation():
    result = subprocess.run([
        "kubectl", "run", "test-pod", "--image=busybox",
        "--restart=Never", "--rm", "-it", "--", "wget", "-qO-",
        "http://other-service:8080]
    ], capture_output=True, text=True, timeout=10)

    if "Connection refused" in result.stderr or "wget: bad address" in result.stderr:
        print("Network isolation correct: cross-namespace blocked")
    else:
        print("Network policy may need review")

Conformance Testing with Sonobuoy

Sonobuoy runs the Kubernetes conformance test suite to verify your cluster meets K8s standards:

sonobuoy run --mode=certified-conformance
sonobuoy status
sonobuoy retrieve .
sonobuoy results *.tar.gz

Practice Questions

1. What is the difference between Kind and Minikube?

Kind runs Kubernetes in Docker containers (fast, good for CI). Minikube runs a VM-based cluster with more features but slower startup.

2. How do you validate a Kubernetes manifest before deploying it?

Use kubectl apply --dry-run=client, kubeconform for schema validation, and kube-linter for best practice checks.

3. Why should you test network policies?

Network policies control pod-to-pod communication. Testing them ensures your security isolation rules work as intended before production.

4. What is Sonobuoy used for?

Sonobuoy runs the Kubernetes conformance suite to verify your cluster passes official K8s conformance tests.

Challenge: Create a Kind-based CI pipeline that deploys a three-tier application (frontend, API, database), runs health checks on each service, validates ConfigMaps and Secrets, and tests network isolation between tiers.

FAQ

What is Kind in Kubernetes testing?

Kind (Kubernetes in Docker) creates lightweight ephemeral clusters for local development and CI testing.

How do I test Helm charts?

Use helm lint for validation, helm template to render manifests, and deploy to Kind for integration testing.

Can I test persistent volumes in Kind?

Yes, Kind supports hostPath volumes and can use local provisioners for stateful workload testing.

How do I simulate pod failures in tests?

Use kubectl delete pod and verify the ReplicaSet recreates it. For chaos testing, inject failures with Litmus or Chaos Mesh.

What's Next

Testing Serverless Applications
Testing Docker Containers
Chaos Testing

Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro