What is the TCP/IP Stack? Explained Simply for DevOps Engineers
TCP/IP is the foundation of all internet communication. Here's a clear explanation of the layers, protocols, and why they matter for debugging network issues in DevOps.
Every network request your application makes — HTTP, database connections, Kubernetes pod communication — goes through the TCP/IP stack. Understanding it helps you debug connection issues, understand network policies, and design better systems.
The Layers
TCP/IP is organized in four layers. Think of each layer as adding an envelope around the data:
Application Layer → HTTP, HTTPS, DNS, SSH, gRPC
Transport Layer → TCP, UDP
Internet Layer → IP (IPv4, IPv6)
Network Access Layer → Ethernet, WiFi (physical transmission)
Each layer adds a header to the data, and the receiving end strips each header back off.
Application Layer
This is where your application lives. You write code that speaks HTTP, gRPC, or PostgreSQL's wire protocol. You don't think about packets or addresses — you just send/receive data.
# HTTP request - application layer
import requests
response = requests.get("https://api.devopsboys.com/posts")
# Database connection - application layer
import psycopg2
conn = psycopg2.connect(host="postgres-service", port=5432, dbname="mydb")The application layer uses well-known port numbers:
- HTTP: 80, HTTPS: 443
- SSH: 22
- PostgreSQL: 5432
- Redis: 6379
- Kafka: 9092
Why it matters for DevOps:
# Check if a port is open (application-level)
curl -v http://my-service:8080/health
# Test TLS certificate
openssl s_client -connect api.devopsboys.com:443
# Check listening ports
ss -tlnp # Linux
netstat -tlnpTransport Layer: TCP vs UDP
The transport layer provides the communication channel between two processes.
TCP (Transmission Control Protocol):
- Connection-based (establishes a connection before sending data)
- Guaranteed delivery (retransmits lost packets)
- In-order delivery (packets arrive in the right order)
- Slower than UDP but reliable
Used by: HTTP, HTTPS, SSH, PostgreSQL, Redis
TCP handshake (3-way):
Client → SYN (I want to connect)
Server → SYN-ACK (I acknowledge, I also want to connect)
Client → ACK (I acknowledge your acknowledgment)
[Connection established — data can flow]
When you see "connection refused" — the server received your SYN but nothing is listening on that port.
When you see "connection timed out" — your SYN packet never reached the server (firewall blocking, wrong IP, network down).
UDP (User Datagram Protocol):
- No connection setup
- No guaranteed delivery (packets can be lost)
- No ordering guarantee
- Much faster and lower overhead than TCP
Used by: DNS (port 53), video streaming, gaming, metrics (StatsD, some Prometheus exporters)
For DevOps:
# Test TCP connectivity
telnet redis-service 6379 # old school
nc -zv redis-service 6379 # modern
# Test UDP
nc -zu dns-service 53
# Watch TCP connections
ss -s # summary statistics
ss -t state established # active TCP connections
# Connection states
ss -tn
# LISTEN → server waiting for connections
# ESTABLISHED → active connection
# TIME_WAIT → connection recently closed (normal, goes away after 2 min)
# CLOSE_WAIT → remote side closed, your app hasn't closed yet (possible bug)CLOSE_WAIT connections that accumulate point to a bug where your application isn't closing connections properly.
Internet Layer: IP Addressing
IP gives every machine an address. Like a street address — needed so packets know where to go.
IPv4: 32-bit address, written as 4 numbers (192.168.1.100)
10.0.0.0/8 Private range (often used in cloud VPCs)
172.16.0.0/12 Private range (often used by Docker)
192.168.0.0/16 Private range (home networks)
127.0.0.1 Loopback (localhost)
CIDR notation: /24 means 24 bits are the network, 8 bits are the host = 254 usable addresses
# Your machine's IP addresses
ip addr show # Linux
# Look for inet 10.0.x.x or 172.x.x.x
# Route table (where traffic goes)
ip route show
# default via 172.17.0.1 ← default gateway (internet traffic goes here)
# 10.0.0.0/24 dev eth0 ← local network traffic
# Trace the path packets take
traceroute api.devopsboys.com
# Shows each router hop between you and the destinationIn Kubernetes: Each pod gets its own IP from the pod CIDR range. The Kubernetes CNI (Cilium, Calico, Flannel) manages this.
kubectl get pod my-app -o wide
# Shows the pod's IP address
# Kubernetes service IPs are virtual (handled by kube-proxy)
kubectl get service my-serviceDNS: The Address Book
DNS translates hostnames to IP addresses. Without it, you'd need to remember IPs for everything.
# Look up a hostname
dig api.devopsboys.com
nslookup api.devopsboys.com
# See which DNS server you're using
cat /etc/resolv.conf
# In Kubernetes, CoreDNS handles DNS
# Service names resolve to ClusterIP
nslookup my-service.my-namespace.svc.cluster.localCommon DNS issues in Kubernetes:
# Pod can't resolve service names
kubectl exec -it my-pod -- nslookup kubernetes.default
# If this fails, CoreDNS is broken
# Check CoreDNS pods
kubectl get pods -n kube-system -l k8s-app=kube-dnsNetwork Access Layer: Physical Transmission
Ethernet, WiFi, fiber — the physical bits traveling between machines. As a DevOps engineer, you rarely interact with this layer directly, but you might see it in:
# Check physical interface stats
ip link show eth0
ethtool eth0 # more detailed stats
# Packet drops at physical layer
ip -s link show eth0 | grep -A 5 "RX:"
# errors: 0 dropped: 123 <- dropped packets could indicate hardware issuesPutting It Together: What Happens When You curl an API
curl https://api.devopsboys.com/posts- DNS lookup: resolve
api.devopsboys.com→ IP104.21.x.x - TCP handshake: SYN → SYN-ACK → ACK to port 443
- TLS handshake: negotiate encryption (HTTPS = HTTP + TLS)
- HTTP request:
GET /posts HTTP/2over the encrypted connection - Response: server sends HTTP response body
- TCP teardown: FIN → ACK → FIN → ACK
Understanding this flow helps when debugging:
- DNS failure: hostname resolves to wrong IP or not at all
- TCP timeout: firewall blocking, server down
- TLS error: certificate expired, hostname mismatch
- HTTP 5xx: application-level error, server running but failing
Debugging Network Issues: Quick Reference
# Is the service reachable? (Layer 3/4)
ping 10.0.0.5 # ICMP ping (may be blocked in Kubernetes)
nc -zv 10.0.0.5 8080 # TCP port check
# DNS working? (Application layer)
dig my-service.default.svc.cluster.local
nslookup my-service
# Is something listening on the port?
ss -tlnp | grep 8080
# Active connections
ss -tn state established
# Packet-level debugging
tcpdump -i eth0 -n port 8080 # capture packets on port 8080
tcpdump -i eth0 host 10.0.0.5 -n # capture traffic to/from specific host
# Network performance
iperf3 -c target-host # bandwidth testThe OSI and TCP/IP models appear abstract, but they map directly to real tools and real debugging. Knowing which layer a problem is at — DNS, TCP connection, TLS, or application — cuts your debugging time in half.
Today I Fixed
Short real fixes from production — posted daily
Stay ahead of the curve
Get the latest DevOps, Kubernetes, AWS, and AI/ML guides delivered straight to your inbox. No spam — just practical engineering content.
Related Articles
What is eBPF? Explained Simply for DevOps Engineers (2026)
eBPF lets you run custom code inside the Linux kernel safely — without writing kernel modules or rebooting. It's why Cilium is fast, why Datadog Agent is lightweight, and why the future of Kubernetes networking looks different. Here's what it actually is.
Build a Kubernetes Cluster with kubeadm from Scratch (2026)
Step-by-step guide to building a real multi-node Kubernetes cluster using kubeadm — no managed services, no shortcuts.
How to Migrate from Ingress-NGINX to Kubernetes Gateway API in 2026
Step-by-step guide to migrating from Ingress-NGINX to Kubernetes Gateway API. Includes YAML examples, implementation choices, testing strategy, and cutover plan.