E-NO
Kubernetes Service local lab 9 Min Read

Kubernetes Service Local Lab Setup with Practical Examples

calendar_today Published: 2026-10-20
update Last Updated: 2026-10-20
analytics SEO Efficiency: 97%
Technical guide illustration for Kubernetes Service Local Lab Setup with Practical Examples.

Intro

Kubernetes Services are fundamental to connecting applications running in pods. They provide stable network identities, load balancing, and service discovery, but their behavior can be subtle, especially when you are troubleshooting DNS, endpoint selection, or network policies. Setting up a dedicated local lab lets you experiment safely, break things deliberately, and build muscle memory for production troubleshooting. This guide walks through a repeatable process for creating a minimal Kubernetes environment on your laptop, deploying example workloads, and exploring Service behavior with concrete commands and expected outputs. By the end, you will have a lab that you can tear down and recreate in minutes, and a set of exercises that reinforce how Services work under the hood.

A clear Kubernetes Service setup reduces rework by separating research, brief, article generation, evaluation, approval, and publishing. In this context, that means separating the learning stages: environment provisioning, workload deployment, Service creation, and verification. For Kubernetes Service local lab, the first useful pilot should be narrow, measurable, and easy to inspect locally before deployment. We will follow that principle by starting with a single-node cluster and a simple application.

Version and Environment Inventory

Before creating any resources, document the versions and topology. This avoids confusion when commands behave differently across Kubernetes releases. The lab described here uses the following components:

ComponentVersionPurpose
Kubernetes1.28 (or latest stable)Core orchestration
kubectl1.28CLI client
minikube1.32Local single-node cluster
Container runtimeDocker 24.x or containerdRuns pods
Example appnginx:1.25Simple web server

These are constructed example versions and can be adjusted. The topology is a single-node cluster with one control plane and no worker nodes (minikube default). This is sufficient for Service experiments because all pods can be scheduled on the same node.

Prerequisites

  • A machine with at least 2 CPUs, 4GB RAM, and 20GB free disk space.
  • A hypervisor such as VirtualBox, Hyper-V, or KVM, or a container runtime like Docker.
  • kubectl installed and in your PATH. Verify with kubectl version --client.
  • minikube installed. Verify with minikube version.

Install minikube and kubectl using your package manager or from the official documentation. For this guide, we assume both are installed.

Quick check 1 of 2

According to the reference passage, what is the default Service type that exposes the Service on an internal IP reachable only from within the cluster?

The passage states that ClusterIP is the default Service type and exposes the Service on an internal IP reachable only from within the cluster.

Safe Configuration Path

We will proceed in small, reversible steps. Each step is independent and can be rolled back by deleting the created resource.

Step 1: Start the Cluster

Start minikube with a specific Kubernetes version to match your documentation. This creates a fresh cluster:

minikube start --kubernetes-version=v1.28.0

Expected output includes lines like:

* minikube v1.32.0 on Ubuntu 22.04
* Using the docker driver based on existing profile
* Starting control plane node minikube in cluster minikube
* Pulling base image ...
* Creating docker container (CPUs=2, Memory=4000MB) ...
* Preparing Kubernetes v1.28.0 on Docker 24.0.7 ...
* Verifying Kubernetes components...
 - Using image gcr.io/k8s-minikube/storage-provisioner: v5
* Enabled addons: storage-provisioner, default-storageclass
* kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'
* Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default

Verify the cluster is accessible:

kubectl cluster-info

Expected output:

Kubernetes control plane is running at https://192.168.49.2:8443
CoreDNS is running at https://192.168.49.2:8443/api/v1/namespaces/kube-system/services/kube-dns: dns/proxy

Step 2: Create a Namespace

Use a dedicated namespace to isolate your lab resources and simplify cleanup.

kubectl create namespace service-lab

Expected output: namespace/service-lab created

Step 3: Deploy a Backend Application

Create a Deployment with two nginx replicas using an imperative command. The pods will serve as the backend for our Service.

kubectl create deployment nginx-deployment --image=nginx:1.25 --replicas=2 --namespace=service-lab

Expected output: deployment.apps/nginx-deployment created

Check pod status:

kubectl get pods -n service-lab -o wide

Expected output (names and IPs will vary):

NAME                                READY   STATUS    RESTARTS   AGE   IP           NODE
nginx-deployment-7c79c4bf97-9x6k2   1/1     Running   0          10s   10.244.0.5   minikube
nginx-deployment-7c79c4bf97-j2p8t   1/1     Running   0          10s   10.244.0.6   minikube

Step 4: Create a ClusterIP Service

Expose the Deployment as a ClusterIP Service using kubectl expose. This is the default Service type and provides internal load balancing. The Service automatically selects the pods based on the Deployment's labels.

kubectl expose deployment nginx-deployment --name=nginx-service --namespace=service-lab --type=ClusterIP --port=80 --target-port=80

Expected output: service/nginx-service exposed

Inspect the Service:

kubectl get service nginx-service -n service-lab -o wide

Expected output:

NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE   SELECTOR
nginx-service   ClusterIP   10.96.100.200   <none>        80/TCP    5s    app=nginx-deployment

Note the CLUSTER-IP is an example; your cluster will assign a different one.

Step 5: Create a NodePort Service (Optional)

To access the Service from outside the cluster, expose the Deployment as a NodePort Service. Kubernetes will assign a random port in the NodePort range. If you need a specific port, you can use kubectl create service nodeport with additional configuration, but for this lab, a random port is sufficient.

kubectl expose deployment nginx-deployment --name=nginx-nodeport --namespace=service-lab --type=NodePort --port=80 --target-port=80

Get the service:

kubectl get service nginx-nodeport -n service-lab

Expected output (the node port is dynamically assigned):

NAME             TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
nginx-nodeport   NodePort   10.96.150.77    <none>        80:3xxxx/TCP   10s

You can access the nginx welcome page by opening http://<minikube-ip>:<nodePort> in a browser, or use minikube service nginx-nodeport -n service-lab to open a tunnel.

Verification and Diagnostics

Now that the Services are running, we verify their behavior using kubectl commands and direct pod-to-service communication.

Check Endpoints

Endpoints are the actual pod IPs backing the Service. Verify that both pod IPs are listed:

kubectl get endpoints nginx-service -n service-lab

Expected output:

NAME            ENDPOINTS                       AGE
nginx-service   10.244.0.5:80,10.244.0.6:80     2m

Test Service from a Pod

We can run a temporary pod and use curl to access the Service by its DNS name. This tests DNS resolution and load balancing.

kubectl run -it --rm --restart=Never --image=curlimages/curl curl-test -n service-lab -- sh

Inside the pod, run:

curl http://nginx-service

Expected output: The HTML content of the nginx welcome page. Press Ctrl-D to exit; the pod will be deleted.

Test load balancing by running curl multiple times and observing the pod logs. In separate terminals, watch logs:

kubectl logs -f -l app=nginx-deployment -n service-lab

As you issue curls, you should see log entries alternating between the two nginx pods, demonstrating round-robin distribution.

Inspect Service Details

Describe the Service to see its configuration and events:

kubectl describe service nginx-service -n service-lab

Expected output includes:

Name:              nginx-service
Namespace:         service-lab
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx-deployment
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.96.100.200
IPs:               10.96.100.200
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.5:80,10.244.0.6:80
Session Affinity:  None
Events:            <none>

Check DNS Resolution

Kubernetes creates a DNS entry for each Service in the form <service-name>.<namespace>.svc.cluster.local. Test it from the curl pod:

nslookup nginx-service.service-lab.svc.cluster.local

Expected output includes the ClusterIP:

Server:         10.96.0.10
Address:        10.96.0.10#53

Name:   nginx-service.service-lab.svc.cluster.local
Address: 10.96.100.200

Common Pitfalls and How to Avoid Them

Working with Kubernetes Services locally often reveals mistakes that also happen in production. Here are the most frequent ones, why they occur, and how to recover.

Pitfall 1: Selector Mismatch Leads to Empty Endpoints

Why it happens: The Service selector does not match any pod labels. This can be due to a typo, using different label keys, or applying the Service before the Deployment is ready.

How to detect: Run kubectl get endpoints nginx-service -n service-lab. If the ENDPOINTS column shows <none>, the Service has no backing pods.

How to recover: Compare the Service selector with pod labels:

kubectl get pods -n service-lab --show-labels
kubectl get service nginx-service -n service-lab -o yaml | grep -A2 selector

Correct the mismatch by updating either the Service selector or the pod template labels, then reapply. A quick fix is to ensure both use app: nginx-deployment.

Pitfall 2: DNS Resolution Fails Inside Pods

Why it happens: CoreDNS pods may be down, or the client pod's DNS policy is set to Default instead of ClusterFirst, causing it to bypass cluster DNS.

How to detect: From inside a pod, run nslookup nginx-service.service-lab.svc.cluster.local. If the lookup times out or returns NXDOMAIN, DNS is not functioning correctly.

How to recover:

kubectl get pods -n kube-system -l k8s-app=kube-dns

If CoreDNS pods are missing or not ready, restart them:

kubectl rollout restart deployment coredns -n kube-system

Also verify the client pod's DNS config:

kubectl exec -n service-lab <pod-name> -- cat /etc/resolv.conf

Ensure the nameserver points to the cluster DNS IP (often 10.96.0.10). If not, check the pod's dnsPolicy setting and set it to ClusterFirst.

Pitfall 3: NodePort Service Not Accessible from Host

Why it happens: With minikube using the Docker driver, the NodePort is exposed on the minikube VM, not directly on localhost. Firewalls or using the wrong IP can also block access.

How to detect: minikube ip returns the VM IP, but curling that IP with the NodePort fails or times out.

How to recover: Use the minikube service command to open a tunnel or get the correct URL:

minikube service nginx-nodeport -n service-lab

This command prints a URL that forwards traffic to the Service. Alternatively, use kubectl port-forward for quick testing:

kubectl port-forward service/nginx-nodeport 8080:80 -n service-lab

Then access http://localhost:8080.

Pitfall 4: Forgetting to Delete Lab Resources

Why it happens: You might leave the cluster running and forget to clean up, consuming local resources.

How to avoid: Always delete the namespace when you finish experiments:

kubectl delete namespace service-lab

This removes all resources in the namespace. If you want to keep the cluster but only remove specific objects, delete them by name:

kubectl delete service nginx-service nginx-nodeport -n service-lab
kubectl delete deployment nginx-deployment -n service-lab

Quick check 2 of 2

Which list of Service types does the reference passage say you can use in a cluster that includes Windows nodes?

The passage explicitly lists NodePort, ClusterIP, LoadBalancer, and ExternalName as the Service types usable in a cluster including Windows nodes.

Failure Modes and Recovery

Services depend on selectors matching pod labels and on network components. Common failures and their recovery steps are listed below.

Failure: Service Has No Endpoints

If the selector does not match any pods, the Service will have empty endpoints.

Diagnosis:

kubectl get endpoints nginx-service -n service-lab

If output shows <none> for ENDPOINTS, check the selector and pod labels.

Recovery:

  • Verify pod labels: kubectl get pods -n service-lab --show-labels
  • Verify Service selector: kubectl get service nginx-service -n service-lab -o yaml | grep -A2 selector
  • Correct the mismatch by editing the Service or Deployment.

Failure: DNS Name Not Resolving

If nslookup inside the pod fails, it may be because CoreDNS is not running or the pod's DNS policy is wrong.

Diagnosis:

kubectl get pods -n kube-system -l k8s-app=kube-dns

Recovery:

  • If CoreDNS pods are missing, restart them: kubectl rollout restart deployment coredns -n kube-system
  • Check pod DNS config: kubectl exec -n service-lab -- cat /etc/resolv.conf

Failure: Service Type NodePort Not Accessible

If you cannot reach the NodePort from your host, check firewall rules or the node's IP.

Diagnosis:

minikube ip
kubectl get service nginx-nodeport -n service-lab

Recovery:

  • Ensure you are using the correct IP and port.
  • For minikube with Docker driver, you may need to use minikube service nginx-nodeport -n service-lab to open a tunnel.

Rollback Strategy

Since resources were created with commands, rollback is simply deleting the created objects.

To remove the entire lab, delete the namespace:

kubectl delete namespace service-lab

Expected output: namespace "service-lab" deleted

Alternatively, delete individual resources using kubectl delete <resource> <name> -n service-lab.

Operations Checklist

Use this checklist each time you set up or modify the lab to ensure consistency.

TaskCommandExpected Result
Start clusterminikube startCluster running, kubectl configured
Create namespacekubectl create namespace service-labNamespace created
Deploy backendkubectl create deployment nginx-deployment --image=nginx:1.25 --replicas=2 -n service-lab2 pods running
Create ClusterIP Servicekubectl expose deployment nginx-deployment --name=nginx-service --type=ClusterIP --port=80 --target-port=80 -n service-labService with ClusterIP assigned
Verify endpointskubectl get endpoints nginx-service -n service-labTwo pod IPs listed
Test from podkubectl run ... curl http://nginx-serviceHTML response
Test DNSnslookup nginx-service.service-lab.svc.cluster.localReturns ClusterIP
Clean upkubectl delete namespace service-labNo resources remaining

After each experiment, capture the commands and outputs in your notes. This builds a personal knowledge base and helps when you move to production.

Conclusion

You now have a functional local Kubernetes Service lab. You have provisioned a single-node cluster, deployed a sample application, created both ClusterIP and NodePort Services, and verified their behavior through endpoints, DNS, and direct access. You have also seen common failure modes and how to recover from them. The next step is to extend the lab: try creating a Service with multiple ports, experiment with externalTrafficPolicy, or add a NetworkPolicy to see how it affects Service access. Because the setup uses simple commands, you can safely iterate and tear down the environment at any time. This lab provides a solid foundation for understanding Kubernetes Services in production. Keep the operations checklist handy and repeat the exercises until the commands become second nature.

Related Research

Article Quality Score

Reader usefulness 97%
  • check_circle Reader-ready guide
  • check_circle Practical examples included
  • check_circle Clean SEO article URL