# Services and Networking Fundamentals

> Chapter 9 of the Courseiva CNCF-CKA curriculum — https://courseiva.com/learn/cncf-cka/services-and-networking-fundamentals

**Official objective:** Services & Networking - 20% — Understand Services, cluster DNS, and Ingress.

## Introduction

Services and Networking Fundamentals. This is the invisible wiring that makes your Kubernetes applications discoverable and reachable, both inside and outside the cluster. For the CKA exam, understanding how Services, cluster DNS, and Ingress work is critical because roughly 20% of the exam score comes from these topics, and they appear in multiple troubleshooting and configuration scenarios.

## The Hotel Concierge Analogy

A hotel concierge stands behind the front desk of a large hotel with hundreds of guest rooms. Guests arrive and depart at all hours, and each guest has a specific room number where they stay. However, the hotel regularly changes which room numbers are assigned to which guests, and sometimes the same guest will stay in different rooms on different visits. The concierge's job is to maintain a consistent way for the outside world to reach any guest—the outside world calls the hotel's main phone number and asks for the guest by name. The concierge then looks up the guest's current room number and forwards the call there. If the guest moves to a different room, the concierge updates the internal directory so that future calls are correctly routed.

This is exactly what a Kubernetes Service does for your application pods. Your pods are like the hotel rooms—they are temporary and can be replaced or moved to different IP addresses. The Service is the concierge, providing a stable phone number (a fixed IP address and DNS name) so that other parts of the system can reliably reach your application without needing to know exactly which room it is in at any moment. Without the Service, every time a pod restarts or scales up, you would have to manually update every client that wants to talk to it.

## Core explanation

Services and networking in Kubernetes solves a fundamental problem: how do you reliably communicate with a set of pods that are constantly being created, destroyed, and moved? In a Kubernetes cluster, every pod gets its own IP address, but that IP address is ephemeral—as soon as the pod is restarted or rescheduled to a different node, it gets a new IP. This makes it impossible to hard-code pod IPs into configurations.

A Service is an abstraction that defines a logical set of pods and a policy by which to access them. Think of it as a stable endpoint that sits in front of a group of pods. When you create a Service, Kubernetes assigns it a virtual IP address (called ClusterIP) that does not change unless you delete and recreate the Service. The Service then uses label selectors to determine which pods belong to its group. Any request sent to the Service's ClusterIP is forwarded to one of the matching pods, distributing the load.

The key components of Service networking:

- ClusterIP: The default type. Exposes the Service on a cluster-internal IP. This means only pods within the cluster can reach it. Useful for internal microservices communication.
- NodePort: Exposes the Service on each node's IP address at a static port (the NodePort). You can access the Service from outside the cluster by visiting <NodeIP>:<NodePort>.
- LoadBalancer: Exposes the Service externally using a cloud provider's load balancer (like AWS ELB or Azure Load Balancer). This is the most common way to expose a production application to the internet.
- ExternalName: Maps the Service to a DNS name (like my.database.example.com) rather than to pods. It returns a CNAME record with that external DNS name.

Every Service also creates a DNS record inside the cluster's DNS system (CoreDNS by default). The DNS name follows the pattern <service-name>.<namespace>.svc.cluster.local. This allows pods to resolve the Service by name, making inter-service communication simple and dynamic.

Cluster DNS is itself a set of pods running the CoreDNS service. It provides name resolution for all Services and pods in the cluster. When a pod tries to reach another Service by name, the DNS query goes to CoreDNS, which returns the ClusterIP of the target Service.

Ingress is a separate resource that manages external access to Services, typically HTTP and HTTPS traffic. While a LoadBalancer Service gives every Service its own public IP, Ingress allows you to have one public endpoint that routes traffic to multiple Services based on rules (like hostname or path). For example, you can have an Ingress rule that sends requests for api.example.com to one Service, and requests for app.example.com to another Service, all through the same load balancer.

Ingress requires an Ingress Controller (like NGINX Ingress Controller or Traefik) to be running in the cluster. The Ingress resource defines the rules, and the controller implements them. Without a controller, Ingress resources have no effect.

Network policies control traffic flow at the IP address or port level. By default, all pods can communicate with each other. Network policies allow you to define rules like "only the frontend pods can talk to the database pods" or "only pods with label 'app: api' can receive traffic from the monitoring system".

Here is how all these pieces fit together in a typical application: an external user sends an HTTP request to the Ingress controller's public IP. The Ingress controller reads the hostname and path, and forwards the request to the appropriate ClusterIP Service. The Service then load-balances the request to one of its backing pods. The pod may need to query a database, so it sends a DNS query to CoreDNS to resolve the database Service's name, gets the ClusterIP, and connects to the database pod directly.

For the CKA exam, you must know how to create and expose Services using kubectl expose and imperative commands. You need to understand how NodePort works—specifically, how to find the port number and the node IP. You must also understand the difference between ClusterIP, NodePort, and LoadBalancer, and when to use each. Troubleshooting DNS resolution inside the cluster is a common task, often requiring you to check the CoreDNS pods and the resolver configuration in /etc/resolv.conf of a pod. Ingress is tested through scenarios where you need to define an Ingress resource with specific host and path rules, and then verify that traffic is correctly routed.

## Real-world context

Imagine you work for a company called QuickShop, an e-commerce platform that runs on Kubernetes. You are the junior platform engineer responsible for deploying and troubleshooting services. One morning, the development team complains that the new 'order-processing' microservice cannot connect to the 'payment-gateway' service.

You start by checking the Services in the namespace. You run 'kubectl get svc -n prod' and see that 'payment-gateway' is listed with a ClusterIP of 10.96.0.15. The 'order-processing' pod is trying to reach 'payment-gateway' by name, but it appears to be timing out. You exec into the pod using 'kubectl exec -it order-processing-pod -- /bin/sh' and run 'nslookup payment-gateway'. The DNS resolution fails—CoreDNS is not returning any records. You then check the CoreDNS pods: 'kubectl get pods -n kube-system | grep coredns'. One of the CoreDNS pods is in CrashLoopBackOff.

You inspect the logs of that CoreDNS pod using 'kubectl logs coredns-pod -n kube-system' and see an error about a misconfigured ConfigMap. You fix the CoreDNS configuration by editing the ConfigMap in the kube-system namespace. After the CoreDNS pod restarts successfully, you rerun the nslookup from the order-processing pod and now it resolves correctly. The development team confirms the microservice is communicating again.

Later that week, the marketing team launches a promotional campaign and expects high traffic. You need to make the frontend application accessible to external users. You have a single public IP and multiple frontend Services (one for the web app, one for the API, one for static assets). You decide to use an Ingress resource with the NGINX Ingress Controller. You create a YAML file with the following rules:

- host: shop.example.com and path: /api/* -> api-service
- host: shop.example.com and path: /* -> web-service
- host: static.shop.example.com -> static-service

You apply the Ingress with 'kubectl apply -f ingress.yaml'. You then test by sending a curl request to the Ingress controller's public IP with the appropriate Host header. The traffic flows correctly to each backend Service.

At the end of the month, the security team asks you to restrict traffic between microservices. You implement NetworkPolicies: you create a policy that only allows the 'api-gateway' Service to access the 'user-db' Service on port 5432, and denies all other traffic. You test by deploying a temporary busybox pod and trying to connect to the database—the connection is refused, confirming the policy works.

In your day-to-day work, you regularly use these commands and actions:

- 'kubectl expose deployment <name> --port=80 --target-port=8080 --type=NodePort --name=<service-name>' to quickly create a Service.
- 'kubectl get endpoints <service-name>' to see which pods are currently behind a Service.
- 'kubectl describe svc <service-name>' to view the details, including the node port and selector.
- 'kubectl run -it --rm debug --image=busybox -- sh' to create a temporary pod for DNS and network testing.
- Editing Ingress resources to add or modify routing rules based on new microservices.

## Exam focus

The CKA exam tests Services and networking in several specific ways. You can expect between 4-7 questions on these topics, spread across the exam. The tasks are hands-on—you will be working in a real Kubernetes cluster via the terminal, not answering multiple choice.

Key exam topics that appear regularly:

- Creating a Service of type ClusterIP, NodePort, or LoadBalancer using imperative kubectl commands. You need to know the exact syntax: 'kubectl expose deployment myapp --port=80 --target-port=8080 --type=NodePort --name=myapp-service'. Traps: they may give you a deployment name that does not exist yet, or they may ask you to expose a pod directly.
- Debugging a Service that is not accessible. Common traps: the Service selector does not match the pod labels, the targetPort is wrong, or the pod is not running (CrashLoopBackOff). The exam will present a broken Service and ask you to fix it.
- Network policy creation. You will be given a scenario requiring a specific NetworkPolicy to allow or deny traffic. Traps: forgetting to define the podSelector correctly, or using incorrect ingress/egress rules. Remember that by default all traffic is allowed, so a NetworkPolicy only restricts traffic if you define rules.
- CoreDNS troubleshooting. You may need to check if DNS resolution works inside a pod. If it fails, the exam expects you to check CoreDNS pods, their logs, and the DNS configuration in the cluster. A common trap is that the CoreDNS service itself might be missing or misconfigured.
- Ingress resource creation. You will be given a YAML file template or asked to create an Ingress from scratch. Traps: forgetting to specify the ingress class name, using the wrong path type (Prefix vs Exact), or not following the exact hostname requirements. The exam environment uses a specific Ingress controller (usually NGINX), and you must specify '.spec.ingressClassName' to match the controller.

Exam traps to watch for:

- When creating a NodePort Service, the exam will not tell you the node IP—you must find it using 'kubectl get nodes -o wide' to see the internal IP.
- When using 'kubectl expose', the --name flag is optional, but if omitted, the Service name defaults to the deployment name. This can confuse you later when you try to reference the Service.
- They love to test the difference between ClusterIP and NodePort by asking you to make a Service accessible from outside the cluster without a LoadBalancer. The expected solution is to change the type to NodePort and then access it via any node's IP and the NodePort.
- DNS names in the cluster follow the pattern '<service>.<namespace>.svc.cluster.local'. They may ask you to specify the full DNS name in a configuration file or in a curl command from another pod.

Key definitions you must memorise for the exam:

- ClusterIP: internal only, stable virtual IP, default type.
- NodePort: exposes on each node's IP at a static port (range 30000-32767).
- LoadBalancer: creates a cloud load balancer and assigns a public IP.
- Ingress: rules-based external access, usually HTTP/HTTPS, requires a controller.
- NetworkPolicy: firewall rules between pods, defined by labels, namespaces, and IP blocks.
- CoreDNS: the cluster DNS server, runs as a deployment in kube-system, manages Service DNS records.
- Endpoints: list of pod IPs that a Service routes traffic to, automatically updated by the kube-controller-manager.

Practical tips: Always check the namespace of the Service and the pod. Misaligned namespaces are a common cause of broken connectivity. Use 'kubectl get pods --show-labels' to verify that your Service selector matches the pod labels exactly.

## Step by step

1. **Identify the pods that need a Service** — First, determine which pods or deployments you want to expose. Look at the labels on those pods because the Service will use a selector to match them. In Kubernetes, Services communicate with pods through label selectors, so the labels must be consistent. Run 'kubectl get pods --show-labels' to see current labels.
2. **Create the Service with the correct type and port mapping** — Use the kubectl expose command or write a YAML file. Specify the port (the port the Service will listen on) and the targetPort (the port the pod container is listening on). Choosing the Service type—ClusterIP, NodePort, or LoadBalancer—determines who can reach the Service. This step is where most configuration errors happen, especially with mismatched ports.
3. **Verify that the Service has endpoints** — Run 'kubectl get endpoints <service-name>' to check if Kubernetes has successfully linked the Service to at least one pod. If the endpoints list is empty, the selector labels do not match any pod labels, or the pods are not running. Without endpoints, traffic to the Service will not be forwarded anywhere.
4. **Test internal connectivity using a temporary pod** — Create a temporary pod with a network tool like busybox and run 'wget -O- http://<service-name>.<namespace>.svc.cluster.local:<port>' or use 'nslookup <service-name>' to verify DNS resolution and network connectivity. This step confirms that the Service is reachable from inside the cluster before exposing it externally.
5. **Expose the Service externally (if needed)** — If the Service type is NodePort, find the node IP and the NodePort from 'kubectl get svc'. If it is LoadBalancer, wait for the external IP to be assigned. For Ingress, create an Ingress resource with rules mapping hostnames or paths to this Service. Then test external access from outside the cluster using a browser or curl.
6. **Apply a NetworkPolicy to secure traffic (optional but important)** — If the application requires restricted communication, create a NetworkPolicy that defines which pods can send traffic to the Service's pods. For example, only allow the frontend Service's pods to reach the database Service's pods. Apply the policy and test connectivity from a non-permitted pod to confirm it is blocked.

## Comparisons

### ClusterIP Service vs NodePort Service

**ClusterIP Service:**
- Only accessible from within the same Kubernetes cluster
- Uses a virtual IP that is stable but not routable externally
- Typical use case: internal microservice communication

**NodePort Service:**
- Accessible from outside the cluster via any node's IP address
- Exposes a static port in the range 30000-32767 on every node
- Typical use case: development or testing, or when a load balancer is not available

### Service vs Ingress

**Service:**
- Works at layer 4 (TCP/UDP) of the network stack
- Provides a stable IP and load-balances traffic to pods
- Each Service typically exposes a single port or port range

**Ingress:**
- Works at layer 7 (HTTP/HTTPS) of the network stack
- Routes traffic based on hostnames and paths, not just IP and port
- Can expose multiple Services through a single public endpoint

### kubectl expose vs kubectl create service

**kubectl expose:**
- Creates a Service based on an existing resource (deployment, pod)
- Automatically sets the selector based on the resource's labels
- Commonly used for quick testing and imperative workflows

**kubectl create service:**
- Creates a Service from scratch without referencing an existing resource
- Requires you to manually specify the selector labels
- Used when you need precise control over the Service definition, especially in YAML files

## Diagram

_Flow of traffic from an external user through an Ingress controller to two Services, then to backend pods, and finally to a database Service with persistent storage._

```mermaid
graph LR
    User[External User] --> Ingress[Ingress Controller]
    Ingress --> Service1[Service: web-app (ClusterIP)]
    Ingress --> Service2[Service: api (ClusterIP)]
    Service1 --> Pod1[Pod: web-abc]
    Service1 --> Pod2[Pod: web-def]
    Service2 --> Pod3[Pod: api-ghi]
    Service2 --> Pod4[Pod: api-jkl]
    Pod3 --> DBService[Service: database (ClusterIP)]
    DBService --> Pod5[Pod: db-1]
    DBService --> Pod6[Pod: db-2]
    Pod5 --> Volume[PersistentVolume]
    Pod6 --> Volume
```

## Common misconceptions

- **Misconception:** A Service exposes a pod directly to the internet, just like a public IP. **Reality:** A Service is a cluster-level abstraction. Only a Service of type LoadBalancer or NodePort provides external access. ClusterIP Services are only reachable within the cluster. (Beginners see the word 'Service' and assume it means external access, but most Services are internal by default in Kubernetes.)
- **Misconception:** If I create a Service with a selector that matches no pods, the Service will still work but will be slow. **Reality:** A Service with no matching pods will have no endpoints, meaning all traffic to the Service will be dropped (no route available). It does not fail slowly. (People assume a Service is always responsive even if no pods exist, because other systems may hide missing backends.)
- **Misconception:** CoreDNS is not important for Services because Services use IP addresses, not DNS. **Reality:** CoreDNS is critical because it provides DNS records for all Services, enabling service discovery by name. Most applications use DNS to find Services, not hardcoded IPs. (Newcomers often think of DNS as optional or only for external domains, not realising that Kubernetes relies on it for internal service discovery.)
- **Misconception:** An Ingress resource automatically sets up an external load balancer and installs the Ingress controller. **Reality:** An Ingress resource only defines routing rules. You must separately deploy an Ingress controller (like NGINX, Traefik, or HAProxy) to implement those rules. Without a controller, the Ingress has no effect. (The name 'Ingress' sounds like it handles all inbound traffic automatically, leading beginners to miss the controller dependency.)
- **Misconception:** Network policies are only for external traffic coming into the cluster. **Reality:** Network policies control traffic between pods inside the cluster, not just external traffic. They can restrict which pods can talk to each other on which ports. (Since the term includes 'network', beginners assume it governs the network boundary, but it actually functions as an internal firewall between pods.)
- **Misconception:** The same Service can be published as both ClusterIP and NodePort simultaneously without changing the type. **Reality:** A given Service can only have one type at a time. If you want both internal and external access, you can create two separate Services pointing to the same pods, or use NodePort (which also creates a ClusterIP automatically). (People think of types as separate capabilities that can be combined, but they are mutually exclusive modes for a single Service object.)

## Key takeaways

- A Kubernetes Service provides a stable IP and DNS name that remains unchanged even as its backing pods are created, destroyed, or moved to different nodes.
- ClusterIP is the default Service type and is only accessible from within the Kubernetes cluster, not from the internet.
- NodePort exposes a Service on a static port (30000-32767) on every node's IP address, enabling external access when a load balancer is not available.
- Ingress allows you to route external HTTP and HTTPS traffic to multiple Services based on hostnames and paths, using a single public endpoint.
- CoreDNS is the internal DNS service that automatically creates DNS records for every Service, allowing pods to find each other by name instead of IP.
- NetworkPolicy acts as a firewall between pods, controlling inbound and outbound traffic based on labels and ports, with the default behaviour being all traffic allowed.

## FAQ

**What is the difference between ClusterIP, NodePort, and LoadBalancer?**

ClusterIP is only accessible inside the cluster. NodePort opens a specific port on every node's IP, letting external traffic in. LoadBalancer provisions a cloud load balancer with a public IP for direct internet access.

**Why is my Service not showing any endpoints?**

The Service selector labels do not match the labels on your pods. Check both sets of labels using 'kubectl describe svc' and 'kubectl get pods --show-labels', and correct the mismatch.

**How do I make my Kubernetes Service accessible from the internet?**

Use a Service of type LoadBalancer if your cloud provider supports it, or type NodePort to access it via any node's IP and the NodePort. Alternatively, use an Ingress resource with an Ingress controller to route HTTP traffic to your Service.

**Does every Service have a DNS name?**

Yes, every Service is automatically assigned a DNS name in the format <service-name>.<namespace>.svc.cluster.local by CoreDNS, which all pods in the cluster can use.

**What is an Ingress controller and do I need it?**

An Ingress controller is a pod that implements the rules defined in Ingress resources (like NGINX or Traefik). Without a controller, Ingress resources have no effect. Most clusters do not come with a controller pre-installed.

**Can I use NetworkPolicy to block traffic to a Service?**

Yes, NetworkPolicy can deny traffic to the pods backing a Service by specifying ingress rules that restrict which sources are allowed. By default, all traffic is allowed, so you must explicitly add deny rules.

## Check your understanding

1. **What command would you use to create a Service of type NodePort that exposes deployment 'myapp' on port 80 with target port 8080?**

   Answer: kubectl expose deployment myapp --port=80 --target-port=8080 --type=NodePort --name=myapp-service

2. **How do you find the external port number of a NodePort Service named 'web-service'?**

   Answer: Run 'kubectl get svc web-service' and look under the PORT(S) column; the NodePort appears after the colon (e.g., 80:30092/TCP means the NodePort is 30092).

3. **Your pod cannot resolve a Service by name internally. What is the most likely cause?**

   Answer: CoreDNS is not running or is misconfigured. Check the CoreDNS pods in the kube-system namespace with 'kubectl get pods -n kube-system | grep coredns' and inspect their logs for errors.

4. **What is the purpose of a NetworkPolicy and what is the default behaviour if no policies are defined?**

   Answer: A NetworkPolicy controls traffic flow between pods at the IP and port level. By default, all traffic between pods is allowed. Once any NetworkPolicy is applied, only traffic that matches the policy rules is permitted.

5. **You need to route requests for 'api.example.com' to one Service and 'app.example.com' to another Service using the same load balancer. Which Kubernetes resource do you need?**

   Answer: You need an Ingress resource with rules defining the hostnames and the backend Services. You also need an Ingress controller (like NGINX) to implement those rules.

---

Interactive version with quiz and diagrams: https://courseiva.com/learn/cncf-cka/services-and-networking-fundamentals
