CKA · Módulo 6CKA · Module 6CKA · Modulo 6 K8s v1.34 Services & Networking 20%

Services: la IP estable frente a pods efímeros

Services: the stable IP in front of ephemeral pods

Service: l'IP stabile davanti a pod effimeri

Los pods nacen, mueren y cambian de IP. El Service es la dirección fija que no cambia: un nombre DNS y una IP virtual que enrutan a los pods vivos que matcheen un selector. Este módulo abre el dominio más grande después de Troubleshooting.

Pods are born, die and change IP. The Service is the fixed address that does not: a DNS name and a virtual IP routing to whichever live pods match a selector. This module opens the largest domain after Troubleshooting.

I pod nascono, muoiono e cambiano IP. Il Service è l'indirizzo fisso che non cambia: un nome DNS e un IP virtuale che instradano ai pod vivi che corrispondono a un selector. Questo modulo apre il dominio più grande dopo Troubleshooting.

Duración70 min
Duration70 min
Durata70 min
DominioServices & Networking
DomainServices & Networking
DominioServices & Networking
Peso20% (1 de 2)
Weight20% (1 of 2)
Peso20% (1 di 2)
RequiereM4 (labels) · M5
RequiresM4 (labels) · M5
RichiedeM4 (label) · M5
Ya sabés crear pods (M4) y decidir dónde corren (M5). Falta el problema que eso deja abierto: ¿cómo le hablás a un pod? Su IP es efímera — se reinicia y cambia; escalás y hay tres IPs nuevas. Hardcodear IPs de pods no funciona nunca. El Service resuelve exactamente eso: una IP virtual estable + un nombre DNS + balanceo entre los pods que matcheen un selector de labels. Y como todo en Kubernetes, el Service no "contiene" pods: los selecciona. Entender esa indirección es entender el 80% del troubleshooting de red.
You can create pods (M4) and decide where they run (M5). What is left is the problem that opens up: how do you talk to a pod? Its IP is ephemeral — restart it and it changes; scale up and there are three new ones. Hardcoding pod IPs never works. The Service solves exactly that: a stable virtual IP + a DNS name + load balancing across the pods matching a label selector. And like everything in Kubernetes, a Service does not "contain" pods: it selects them. Understanding that indirection is understanding 80% of network troubleshooting.
Sai creare pod (M4) e decidere dove girano (M5). Resta il problema che questo apre: come si parla a un pod? Il suo IP è effimero — si riavvia e cambia; scali e ce ne sono tre nuovi. Cablare gli IP dei pod non funziona mai. Il Service risolve esattamente questo: un IP virtuale stabile + un nome DNS + bilanciamento fra i pod che corrispondono a un selector di label. E come tutto in Kubernetes, un Service non "contiene" pod: li seleziona. Capire quell'indirezione è capire l'80% del troubleshooting di rete.
Modelo mental del módulo
Module mental model
Modello mentale del modulo
Service = SELECTOR + PUERTOS → EndpointSlice
Service = SELECTOR + PORTS → EndpointSlice
Service = SELECTOR + PORTE → EndpointSlice
El selector define a quién apunta (labels de pods), los puertos definen cómo (port → targetPort). El resultado es una lista de IP:puerto de pods Ready: el EndpointSlice. Si esa lista está vacía, el Service no sirve a nadie — y ese es el primer lugar donde mirás cuando algo de red no funciona.
The selector defines who it points at (pod labels), the ports define how (port → targetPort). The result is a list of IP:port for Ready pods: the EndpointSlice. If that list is empty, the Service serves nobody — and that is the first place you look when networking misbehaves.
Il selector definisce chi punta (label dei pod), le porte definiscono come (port → targetPort). Il risultato è una lista di IP:porta dei pod Ready: l'EndpointSlice. Se quella lista è vuota, il Service non serve nessuno — ed è il primo posto dove guardare quando la rete non va.
6.1
El Service y el modelo de red
The Service and the network model
Il Service e il modello di rete
IP virtual, selector, endpoints, port vs targetPort.
Virtual IP, selector, endpoints, port vs targetPort.
IP virtuale, selector, endpoint, port contro targetPort.
6.2
Los tipos de Service
The Service types
I tipi di Service
ClusterIP, NodePort, LoadBalancer, ExternalName, headless.
6.3
Crear services rápido
Creating services fast
Creare service in fretta
expose, create service, edición de puertos.
expose, create service, editing ports.
expose, create service, modifica delle porte.
6.4
CoreDNS: descubrimiento
CoreDNS: discovery
CoreDNS: discovery
FQDN, resolución cross-namespace, DNS de StatefulSet.
FQDN, cross-namespace resolution, StatefulSet DNS.
FQDN, risoluzione cross-namespace, DNS degli StatefulSet.
6.5
kube-proxy & EndpointSlices
Cómo se implementa realmente. Debug del camino.
How it is really implemented. Debugging the path.
Come è davvero implementato. Debug del percorso.
★
Práctica · 9 ejercicios
Practice · 9 exercises
Pratica · 9 esercizi
Del expose al DNS, más 4 de troubleshooting, con manifest listo para aplicar.
From expose to DNS, plus 4 troubleshooting drills, each with a ready-to-apply manifest.
Dall'expose al DNS, più 4 drill di troubleshooting, ognuno con un manifest pronto da applicare.
6.1
El primitivo · 15 min
The primitive · 15 min
Il primitivo · 15 min

El Service y el modelo de red

The Service and the network model

Il Service e il modello di rete

Una IP que no cambia, delante de pods que sí cambian.
An IP that does not change, in front of pods that do.
Un IP che non cambia, davanti a pod che cambiano.
Práctica · Crear y verificar
Practice · Create and verify
Pratica · Creare e verificare

El problema, en vivo

The problem, live

Il problema, dal vivo

# Las IPs de los pods son efímeras: mirá y volvé a mirar# Pod IPs are ephemeral: look, then look again# Gli IP dei pod sono effimeri: guarda, e riguarda
k create deploy web --image=nginx --replicas=3
k get pods -o wide          # anotá una IP# note one IP# annota un IP
k delete pod -l app=web
k get pods -o wide          # IPs nuevas, otro pod# new IPs, different pods# IP nuovi, altri pod

El Service, imperativo

The Service, imperatively

Il Service, imperativo

# expose: crea el Service tomando el selector del deploy# expose: creates the Service taking the deploy's selector# expose: crea il Service prendendo il selector del deploy
k expose deploy web --port=80 --target-port=80

k get svc web
# NAME  TYPE       CLUSTER-IP     PORT(S)
# web   ClusterIP  10.96.140.22   80/TCP

La verificación que importa: ¿tiene endpoints?

The verification that matters: does it have endpoints?

La verifica che conta: ha endpoint?

# La lista real de pods detrás del Service# The real list of pods behind the Service# La lista reale dei pod dietro il Service
k get endpointslices -l kubernetes.io/service-name=web
k describe svc web       # campo Endpoints# Endpoints field# campo Endpoints

# Probarlo desde dentro del cluster# Test it from inside the cluster# Provarlo da dentro il cluster
k run tmp --rm -it --image=nginx -- curl -s web:80

El YAML, para leerlo bien

The YAML, read properly

Lo YAML, letto bene

apiVersion: v1
kind: Service
metadata:
  name: web
spec:
  selector:              # A QUIÉN apunta (labels de POD)# WHO it targets (POD labels)# CHI punta (label dei POD)
    app: web
  ports:
  - port: 80             # puerto DEL SERVICE# the SERVICE's port# porta DEL SERVICE
    targetPort: 8080     # puerto DEL CONTAINER# the CONTAINER's port# porta DEL CONTAINER
    protocol: TCP
⚠
El selector matchea labels de pods, no del Deployment. Si le pasás el label del Deployment y los pods tienen otro, el Service queda sin endpoints y todo falla en silencio: la IP responde, pero nadie contesta.
The selector matches pod labels, not the Deployment's. Give it the Deployment's label while pods carry another and the Service ends up with no endpoints, failing silently: the IP answers, but nobody replies.
Il selector corrisponde alle label dei pod, non del Deployment. Se gli passi la label del Deployment mentre i pod ne hanno un'altra, il Service resta senza endpoint e fallisce in silenzio: l'IP risponde, ma nessuno replica.
Teoría · La indirección
Theory · The indirection
Teoria · L'indirezione

El modelo de red de Kubernetes

Kubernetes' network model

Il modello di rete di Kubernetes

Tres reglas que el CNI (Calico, en tu cluster) garantiza:

Three rules the CNI (Calico, in your cluster) guarantees:

Tre regole che il CNI (Calico, nel tuo cluster) garantisce:

  • Cada pod tiene su propia IP, única en el cluster.
  • Todo pod puede hablar con todo pod sin NAT, esté donde esté.
  • Los nodos pueden hablar con los pods sin NAT.
  • Every pod has its own IP, unique in the cluster.
  • Any pod can talk to any pod without NAT, wherever it sits.
  • Nodes can talk to pods without NAT.
  • Ogni pod ha il proprio IP, unico nel cluster.
  • Ogni pod può parlare con ogni pod senza NAT, ovunque si trovi.
  • I nodi possono parlare con i pod senza NAT.

Es una red plana. Por eso no hay "port mapping" tipo Docker: cada pod tiene sus puertos propios.

It is a flat network. That is why there is no Docker-style "port mapping": each pod has its own ports.

È una rete piatta. Per questo non c'è "port mapping" alla Docker: ogni pod ha le proprie porte.

Entonces, ¿para qué el Service?

So what is the Service for?

Allora a cosa serve il Service?

La red plana resuelve conectividad, no descubrimiento. El Service agrega tres cosas que la red no da: una IP estable, un nombre DNS y balanceo entre réplicas.

The flat network solves connectivity, not discovery. The Service adds three things the network does not: a stable IP, a DNS name and load balancing across replicas.

La rete piatta risolve la connettività, non la discovery. Il Service aggiunge tre cose che la rete non dà: un IP stabile, un nome DNS e il bilanciamento fra repliche.

Los tres puertos (fuente eterna de confusión)

The three ports (an eternal source of confusion)

Le tre porte (fonte eterna di confusione)

CampoEs el puerto de…
FieldIs the port of…
CampoÈ la porta di…
portel Service (por donde le hablás)
portthe Service (where you address it)
portil Service (dove gli parli)
targetPortel container (a donde reenvía)
targetPortthe container (where it forwards)
targetPortil container (dove inoltra)
nodePortel nodo (solo tipo NodePort/LB)
nodePortthe node (NodePort/LB types only)
nodePortil nodo (solo tipi NodePort/LB)

Si omitís targetPort, asume el mismo valor que port. Fuente clásica de "conecta pero da error".

Omit targetPort and it assumes the same value as port. A classic source of "it connects but errors".

Se ometti targetPort, assume lo stesso valore di port. Fonte classica di "si connette ma dà errore".

Solo pods Ready entran

Only Ready pods get in

Entrano solo i pod Ready

El endpoint incluye únicamente pods que pasan su readinessProbe. Esa es la conexión con las probes (M9 §9.3): una readinessProbe mal configurada saca al pod del balanceo aunque el pod esté Running y la app funcione.

The endpoint includes only pods passing their readinessProbe. That is the link to probes (M9 §9.3): a misconfigured readinessProbe pulls the pod out of the balancing even while it is Running and the app works.

L'endpoint include solo i pod che superano la loro readinessProbe. È il collegamento con le probe (M9 §9.3): una readinessProbe mal configurata toglie il pod dal bilanciamento anche se è Running e l'app funziona.

★
Mantra de troubleshooting de red: Service sin endpoints = selector que no matchea, o pods no Ready. Son el 90% de los casos. Siempre empezás por k describe svc.
Network troubleshooting mantra: Service with no endpoints = a selector that does not match, or pods not Ready. That is 90% of cases. You always start at k describe svc.
Mantra del troubleshooting di rete: Service senza endpoint = un selector che non corrisponde, o pod non Ready. È il 90% dei casi. Si parte sempre da k describe svc.
6.2
Exposición · 20 min
Exposure · 20 min
Esposizione · 20 min

Los tipos de Service

The Service types

I tipi di Service

Misma mecánica, distinto alcance: interno, por nodo, o externo.
Same mechanics, different reach: internal, per node, or external.
Stessa meccanica, portata diversa: interna, per nodo, o esterna.
Práctica · Cada tipo
Practice · Each type
Pratica · Ogni tipo

ClusterIP (el default) — solo interno

ClusterIP (the default) — internal only

ClusterIP (il default) — solo interno

k expose deploy web --port=80
# Accesible solo desde dentro: web, web.default.svc.cluster.local# Reachable only from inside: web, web.default.svc.cluster.local# Raggiungibile solo da dentro: web, web.default.svc.cluster.local

NodePort — puerto en TODOS los nodos

NodePort — a port on EVERY node

NodePort — una porta su TUTTI i nodi

k expose deploy web --port=80 --type=NodePort
k get svc web
# PORT(S): 80:31234/TCP   <- 31234 = nodePort

# Desde tu máquina, contra la IP de CUALQUIER nodo# From your machine, against ANY node's IP# Dalla tua macchina, contro l'IP di QUALSIASI nodo
k get nodes -o wide
curl http://<IP-NODO>:31234

Rango por defecto: 30000-32767. Podés fijarlo con nodePort: 30080 en el YAML.

Default range: 30000-32767. You can pin it with nodePort: 30080 in the YAML.

Range di default: 30000-32767. Puoi fissarlo con nodePort: 30080 nello YAML.

LoadBalancer — IP externa del proveedor

LoadBalancer — the provider's external IP

LoadBalancer — l'IP esterno del provider

k expose deploy web --port=80 --type=LoadBalancer
k get svc web
# EXTERNAL-IP: <pending>  <- en kubeadm bare-metal, PARA SIEMPRE# EXTERNAL-IP: <pending>  <- on bare-metal kubeadm, FOREVER# EXTERNAL-IP: <pending>  <- su kubeadm bare-metal, PER SEMPRE

ExternalName — un CNAME, sin proxy

ExternalName — a CNAME, no proxying

ExternalName — un CNAME, senza proxy

spec:
  type: ExternalName
  externalName: db.ejemplo.com
# Sin selector, sin ClusterIP: DNS devuelve un CNAME y listo# No selector, no ClusterIP: DNS returns a CNAME and that is it# Nessun selector, nessun ClusterIP: il DNS restituisce un CNAME e basta

Headless — sin IP virtual, DNS directo a pods

Headless — no virtual IP, DNS straight to pods

Headless — nessun IP virtuale, DNS diretto ai pod

spec:
  clusterIP: None       # esto lo vuelve headless# this makes it headless# questo lo rende headless
  selector:
    app: db

# nslookup devuelve las IPs de los pods, no una VIP# nslookup returns the pod IPs, not a VIP# nslookup restituisce gli IP dei pod, non una VIP
★
En el examen, "exponer para acceso externo" con un cluster kubeadm significa NodePort o Ingress (M7) — nunca LoadBalancer, que se queda en <pending> sin un controller como MetalLB. Leé bien qué te piden.
In the exam, "expose for external access" on a kubeadm cluster means NodePort or Ingress (M7) — never LoadBalancer, which stays <pending> without a controller like MetalLB. Read carefully what is asked.
All'esame, "esporre per l'accesso esterno" su un cluster kubeadm significa NodePort o Ingress (M7) — mai LoadBalancer, che resta <pending> senza un controller come MetalLB. Leggi bene cosa chiedono.
Teoría · Alcance y anidamiento
Theory · Reach and nesting
Teoria · Portata e annidamento

Los tipos, en una tabla

The types, in one table

I tipi, in una tabella

TipoAlcanceUso típico
TypeReachTypical use
TipoPortataUso tipico
ClusterIPInternoComunicación entre servicios
ClusterIPInternalService-to-service traffic
ClusterIPInternoTraffico fra servizi
NodePortIP nodo + puertoAcceso externo básico / labs
NodePortNode IP + portBasic external access / labs
NodePortIP nodo + portaAccesso esterno base / lab
LoadBalancerIP públicaProducción en la nube
LoadBalancerPublic IPCloud production
LoadBalancerIP pubblicoProduzione in cloud
ExternalNameSolo DNSApuntar a algo de afuera
ExternalNameDNS onlyPointing at something outside
ExternalNameSolo DNSPuntare a qualcosa di esterno

Se anidan (esto ordena todo)

They nest (this sorts everything out)

Si annidano (questo mette ordine)

NodePort incluye ClusterIP. LoadBalancer incluye NodePort, que incluye ClusterIP. No son alternativas excluyentes: son capas. Un Service NodePort sigue teniendo su ClusterIP y su nombre DNS interno funcionando igual.

NodePort includes ClusterIP. LoadBalancer includes NodePort, which includes ClusterIP. They are not mutually exclusive alternatives: they are layers. A NodePort Service still has its ClusterIP and its internal DNS name working just the same.

NodePort include ClusterIP. LoadBalancer include NodePort, che include ClusterIP. Non sono alternative escludenti: sono strati. Un Service NodePort mantiene il suo ClusterIP e il suo nome DNS interno funzionanti come prima.

Headless: para qué existe

Headless: why it exists

Headless: perché esiste

Con clusterIP: None no hay VIP ni balanceo: el DNS devuelve todas las IPs de los pods. Sirve cuando el cliente necesita elegir instancia — bases de datos con réplicas, y sobre todo StatefulSets, donde cada pod tiene identidad propia (M4).

With clusterIP: None there is no VIP and no balancing: DNS returns all the pod IPs. Useful when the client must pick an instance — replicated databases, and above all StatefulSets, where each pod has its own identity (M4).

Con clusterIP: None non c'è VIP né bilanciamento: il DNS restituisce tutti gli IP dei pod. Serve quando il client deve scegliere l'istanza — database con repliche, e soprattutto StatefulSet, dove ogni pod ha identità propria (M4).

externalTrafficPolicy

  • Cluster (default): el tráfico que entra por un nodo puede reenviarse a un pod en otro nodo. Balancea mejor, pierde la IP de origen.
  • Local: solo a pods del mismo nodo. Preserva la IP de origen, pero si ese nodo no tiene pods, se cae.
  • Cluster (default): traffic entering one node may be forwarded to a pod on another. Balances better, loses the source IP.
  • Local: only pods on the same node. Preserves the source IP, but if that node has no pods, it drops.
  • Cluster (default): il traffico che entra da un nodo può essere inoltrato a un pod su un altro. Bilancia meglio, perde l'IP di origine.
  • Local: solo pod dello stesso nodo. Preserva l'IP di origine, ma se quel nodo non ha pod, cade.
★
Un NodePort abre el puerto en todos los nodos, no solo en los que tienen pods. Pegale a cualquiera y kube-proxy enruta al pod correcto, esté donde esté.
A NodePort opens the port on every node, not only those with pods. Hit any of them and kube-proxy routes to the right pod, wherever it is.
Un NodePort apre la porta su tutti i nodi, non solo su quelli con pod. Colpisci uno qualsiasi e kube-proxy instrada al pod giusto, ovunque sia.
VisorExplorerVisore · los 4 tipos de Service, en vivothe 4 Service types, livei 4 tipi di Service, dal vivo

Hacé clic en cualquier pod para que falle su readinessProbe y mirá qué pasa con los endpoints.

Click any pod to make its readinessProbe fail, and watch what happens to the endpoints.

Clicca un pod qualsiasi per far fallire la sua readinessProbe e guarda cosa succede agli endpoint.

6.3
Velocidad · 10 min
Speed · 10 min
Velocità · 10 min

Crear services rápido

Creating services fast

Creare service in fretta

Dos caminos imperativos, y cuándo usar cada uno.
Two imperative paths, and when to use each.
Due strade imperative, e quando usare ciascuna.
Práctica · Los dos caminos
Practice · The two paths
Pratica · Le due strade

Camino 1: expose (recurso existente)

Path 1: expose (existing resource)

Strada 1: expose (risorsa esistente)

# Toma el selector del recurso automáticamente# Takes the resource's selector automatically# Prende automaticamente il selector della risorsa
k expose deploy web --port=80 --target-port=8080
k expose pod mypod --port=80 --name=mypod-svc
k expose deploy web --port=80 --type=NodePort

# Generar el YAML sin crear (para editar el nodePort)# Generate the YAML without creating (to edit the nodePort)# Generare lo YAML senza creare (per modificare il nodePort)
k expose deploy web --port=80 --type=NodePort $do > svc.yaml

Camino 2: create service (desde cero)

Path 2: create service (from scratch)

Strada 2: create service (da zero)

# Formato de puertos: --tcp=PORT:TARGETPORT# Port format: --tcp=PORT:TARGETPORT# Formato porte: --tcp=PORT:TARGETPORT
k create service clusterip mysvc --tcp=80:8080
k create service nodeport mysvc --tcp=80:8080 --node-port=30080
k create service externalname ext --external-name=db.ejemplo.com

El atajo que te ahorra un Service

The shortcut that saves you a Service

La scorciatoia che ti risparmia un Service

# run + expose en un comando (crea pod Y ClusterIP)# run + expose in one command (creates pod AND ClusterIP)# run + expose in un comando (crea pod E ClusterIP)
k run web --image=nginx --port=80 --expose

Editar puertos después

Editing ports afterwards

Modificare le porte dopo

k edit svc web                        # puertos y tipo: editables en vivo# ports and type: editable live# porte e tipo: modificabili dal vivo
k patch svc web -p '{"spec":{"type":"NodePort"}}'
⚠
create service arma su propio selector (app: mysvc) que probablemente no matchee tus pods. Si lo usás, verificá los endpoints o corregí el selector a mano. Con expose ese problema no existe.
create service invents its own selector (app: mysvc) that probably does not match your pods. If you use it, check the endpoints or fix the selector by hand. With expose that problem does not exist.
create service si inventa il proprio selector (app: mysvc) che probabilmente non corrisponde ai tuoi pod. Se lo usi, controlla gli endpoint o correggi il selector a mano. Con expose quel problema non esiste.
Teoría · Cuál elegir
Theory · Which to pick
Teoria · Quale scegliere

La regla

The rule

La regola

expose cuando el workload ya existe — hereda el selector correcto y es imposible equivocarse. create service solo cuando necesitás un Service sin workload detrás (o un ExternalName).

expose when the workload already exists — it inherits the right selector and you cannot get it wrong. create service only when you need a Service with no workload behind it (or an ExternalName).

expose quando il workload esiste già — eredita il selector giusto ed è impossibile sbagliare. create service solo quando serve un Service senza workload dietro (o un ExternalName).

Multi-puerto: los nombres son obligatorios

Multi-port: names are mandatory

Multi-porta: i nomi sono obbligatori

Si un Service expone más de un puerto, cada entrada debe tener name. Con un solo puerto es opcional. La API rechaza el objeto si te lo olvidás.

If a Service exposes more than one port, each entry must have a name. With a single port it is optional. The API rejects the object if you forget.

Se un Service espone più di una porta, ogni voce deve avere un name. Con una sola porta è opzionale. L'API rifiuta l'oggetto se lo dimentichi.

targetPort puede ser un nombre

targetPort can be a name

targetPort può essere un nome

targetPort: http resuelve al containerPort llamado http en el pod. Más robusto: el Service no se rompe si cambia el número.

targetPort: http resolves to the containerPort named http in the pod. More robust: the Service does not break if the number changes.

targetPort: http risolve al containerPort chiamato http nel pod. Più robusto: il Service non si rompe se il numero cambia.

★
Recordá el $do del M0 (--dry-run=client -o yaml): para cualquier cosa que expose no soporte por flag (nodePort fijo, sessionAffinity, headless), generás el YAML, editás una línea y aplicás. Sigue siendo más rápido que escribirlo desde cero.
Remember M0's $do (--dry-run=client -o yaml): for anything expose has no flag for (a pinned nodePort, sessionAffinity, headless), you generate the YAML, edit one line and apply. Still faster than writing it from scratch.
Ricorda il $do del M0 (--dry-run=client -o yaml): per qualunque cosa expose non supporti con un flag (nodePort fisso, sessionAffinity, headless), generi lo YAML, modifichi una riga e applichi. Resta più rapido che scriverlo da zero.
6.4
Descubrimiento · 15 min
Discovery · 15 min
Discovery · 15 min

CoreDNS: hablarle por nombre

CoreDNS: addressing by name

CoreDNS: parlargli per nome

La IP del Service tampoco se hardcodea. Se usa el nombre.
The Service IP is not hardcoded either. You use the name.
Nemmeno l'IP del Service si cabla. Si usa il nome.
Práctica · Resolver nombres
Practice · Resolving names
Pratica · Risolvere nomi

CoreDNS vive en kube-system

CoreDNS lives in kube-system

CoreDNS vive in kube-system

k get pods -n kube-system -l k8s-app=kube-dns
k get svc -n kube-system kube-dns   # normalmente 10.96.0.10# usually 10.96.0.10# di solito 10.96.0.10

# Su config es un ConfigMap (el Corefile)# Its config is a ConfigMap (the Corefile)# La sua config è una ConfigMap (il Corefile)
k -n kube-system get cm coredns -o yaml

Probar resolución desde un pod

Testing resolution from a pod

Provare la risoluzione da un pod

# busybox:1.28 — las versiones nuevas tienen nslookup roto# busybox:1.28 — newer versions have a broken nslookup# busybox:1.28 — le versioni nuove hanno nslookup rotto
k run dns --rm -it --image=busybox:1.28 -- sh

# dentro del pod:# inside the pod:# dentro il pod:
nslookup web                         # mismo namespace# same namespace# stesso namespace
nslookup web.default                    # cross-namespace
nslookup web.default.svc.cluster.local
cat /etc/resolv.conf                    # nameserver + search domains

Lo que ves en resolv.conf

What you see in resolv.conf

Cosa vedi in resolv.conf

nameserver 10.96.0.10
search default.svc.cluster.local svc.cluster.local cluster.local
options ndots:5

Por eso web solo funciona: los search domains completan el FQDN.

That is why bare web works: the search domains complete the FQDN.

Per questo il solo web funziona: i search domain completano l'FQDN.

DNS de StatefulSet (headless)

StatefulSet DNS (headless)

DNS degli StatefulSet (headless)

# Cada pod tiene su nombre estable:# Each pod has its own stable name:# Ogni pod ha il suo nome stabile:
#   POD-N.SERVICIO.NAMESPACE.svc.cluster.local
nslookup db-0.db.default.svc.cluster.local
⚠
Si el DNS no resuelve: 1) ¿corren los pods de CoreDNS? 2) ¿el Service kube-dns tiene endpoints? 3) ¿el nameserver del pod apunta a esa IP? En tu cluster, CoreDNS quedó Pending hasta que instalaste el CNI — sin red de pods, no hay DNS.
If DNS does not resolve: 1) are the CoreDNS pods running? 2) does the kube-dns Service have endpoints? 3) does the pod's nameserver point at that IP? In your cluster CoreDNS stayed Pending until you installed the CNI — no pod network, no DNS.
Se il DNS non risolve: 1) i pod di CoreDNS girano? 2) il Service kube-dns ha endpoint? 3) il nameserver del pod punta a quell'IP? Nel tuo cluster CoreDNS è rimasto Pending finché non hai installato il CNI — senza rete dei pod, niente DNS.
Teoría · El esquema de nombres
Theory · The naming scheme
Teoria · Lo schema dei nomi

El FQDN de un Service

A Service's FQDN

L'FQDN di un Service

ParteQué es
PartWhat it is
ParteCos'è
webnombre del Service
webthe Service's name
webil nome del Service
defaultnamespace
defaultnamespace
defaultnamespace
svctipo de recurso
svcresource type
svctipo di risorsa
cluster.localdominio del cluster
cluster.localthe cluster domain
cluster.localil dominio del cluster

Completo: web.default.svc.cluster.local

In full: web.default.svc.cluster.local

Per intero: web.default.svc.cluster.local

La regla que hay que tener automatizada

The rule that must be automatic

La regola che deve essere automatica

  • Mismo namespace → alcanza web.
  • Otro namespace → web.otrons como mínimo.
  • Un pod en dev pidiendo web busca web.dev..., NO web.default....
  • Same namespace → plain web is enough.
  • Another namespace → web.otherns at minimum.
  • A pod in dev asking for web looks up web.dev..., NOT web.default....
  • Stesso namespace → basta web.
  • Altro namespace → web.altrons come minimo.
  • Un pod in dev che chiede web cerca web.dev..., NON web.default....

Qué se resuelve y qué no

What resolves and what does not

Cosa risolve e cosa no

CoreDNS crea registros A para todos los Services. Los pods también tienen registro (10-244-1-5.default.pod.cluster.local, con guiones), pero casi nunca se usa: a los pods se les habla vía Service.

CoreDNS creates A records for every Service. Pods get records too (10-244-1-5.default.pod.cluster.local, with dashes), but it is almost never used: you talk to pods through a Service.

CoreDNS crea record A per ogni Service. Anche i pod hanno record (10-244-1-5.default.pod.cluster.local, con trattini), ma non si usa quasi mai: ai pod si parla tramite un Service.

ndots:5, el detalle raro

ndots:5, the odd detail

ndots:5, il dettaglio strano

Un nombre con menos de 5 puntos se prueba primero contra los search domains. Es la razón por la que los nombres cortos funcionan, y también de latencia extra al resolver dominios externos.

A name with fewer than 5 dots is tried against the search domains first. That is why short names work — and also why resolving external domains costs extra latency.

Un nome con meno di 5 punti viene provato prima contro i search domain. È il motivo per cui i nomi corti funzionano, e anche della latenza extra nel risolvere domini esterni.

dnsPolicy: quién decide ese resolv.conf

dnsPolicy: who decides that resolv.conf

dnsPolicy: chi decide quel resolv.conf

El resolv.conf que ves no cae del cielo: lo escribe el kubelet según spec.dnsPolicy del pod. Y el nombre de los valores es engañoso.

The resolv.conf you see does not fall from the sky: the kubelet writes it according to the pod's spec.dnsPolicy. And the value names are misleading.

Il resolv.conf che vedi non cade dal cielo: lo scrive il kubelet secondo lo spec.dnsPolicy del pod. E i nomi dei valori sono ingannevoli.

dnsPolicyEl pod usa
dnsPolicyThe pod uses
dnsPolicyIl pod usa
ClusterFirstEl default real. CoreDNS, con los search del cluster
ClusterFirstThe actual default. CoreDNS, with the cluster search domains
ClusterFirstIl default vero. CoreDNS, coi search domain del cluster
DefaultEl resolv.conf del nodo. No conoce el DNS del cluster
DefaultThe node's resolv.conf. It knows nothing of cluster DNS
DefaultIl resolv.conf del nodo. Non conosce il DNS del cluster
NoneNada: lo definís vos entero en dnsConfig
NoneNothing: you define it all yourself in dnsConfig
NoneNulla: lo definisci tu per intero in dnsConfig
ClusterFirstWithHostNetCoreDNS aun con hostNetwork: true
ClusterFirstWithHostNetCoreDNS even with hostNetwork: true
ClusterFirstWithHostNetCoreDNS anche con hostNetwork: true

La trampa: Default NO es el default. El default es ClusterFirst. Un pod con dnsPolicy: Default resuelve internet perfecto pero no encuentra ningún Service del cluster — y el síntoma es un solo pod que no resuelve mientras el resto anda. Ahí no mires CoreDNS: compará el resolv.conf del pod sano contra el del roto.

The trap: Default is NOT the default. The default is ClusterFirst. A pod with dnsPolicy: Default resolves the internet perfectly but finds no cluster Service — and the symptom is one pod not resolving while the rest are fine. Do not look at CoreDNS there: compare the healthy pod's resolv.conf against the broken one's.

La trappola: Default NON è il default. Il default è ClusterFirst. Un pod con dnsPolicy: Default risolve internet benissimo ma non trova alcun Service del cluster — e il sintomo è un solo pod che non risolve mentre gli altri vanno. Lì non guardare CoreDNS: confronta il resolv.conf del pod sano con quello rotto.

★
"El pod A no puede hablarle al pod B" en el examen casi siempre es: Service sin endpoints, nombre DNS mal escrito (falta el namespace) o una NetworkPolicy (M7). Verificás en ese orden.
"Pod A cannot talk to pod B" in the exam is nearly always: a Service with no endpoints, a misspelled DNS name (missing namespace) or a NetworkPolicy (M7). Check in that order.
"Il pod A non riesce a parlare col pod B" all'esame è quasi sempre: un Service senza endpoint, un nome DNS sbagliato (manca il namespace) o una NetworkPolicy (M7). Verifica in quell'ordine.
6.5
Bajo el capó · 10 min
Under the hood · 10 min
Sotto il cofano · 10 min

kube-proxy & EndpointSlices

La ClusterIP no existe en ninguna interfaz. Entender por qué.
The ClusterIP exists on no interface. Understanding why.
Il ClusterIP non esiste su nessuna interfaccia. Capire perché.
Práctica · Seguir el camino
Practice · Follow the path
Pratica · Seguire il percorso

kube-proxy es un DaemonSet

kube-proxy is a DaemonSet

kube-proxy è un DaemonSet

k get ds -n kube-system kube-proxy
k logs -n kube-system -l k8s-app=kube-proxy --tail=20

# Su modo está en el ConfigMap# Its mode lives in the ConfigMap# La sua modalità sta nella ConfigMap
k -n kube-system get cm kube-proxy -o yaml | grep -i mode

EndpointSlices: la fuente de verdad

EndpointSlices: the source of truth

EndpointSlice: la fonte di verità

# Lo moderno# The modern way# Il modo moderno
k get endpointslices
k get endpointslices -l kubernetes.io/service-name=web -o yaml

# Lo viejo (deprecado, pero todavía responde)# The old way (deprecated, still answers)# Il modo vecchio (deprecato, risponde ancora)
k get endpoints web

La secuencia de diagnóstico completa

The complete diagnostic sequence

La sequenza diagnostica completa

# 1. ¿Existe el Service y qué selector tiene?# 1. Does the Service exist and what is its selector?# 1. Il Service esiste e qual è il suo selector?
k get svc web -o wide

# 2. ¿Hay pods con ESE label?# 2. Are there pods with THAT label?# 2. Ci sono pod con QUELLA label?
k get pods -l app=web

# 3. ¿Están Ready? (solo los Ready entran)# 3. Are they Ready? (only Ready ones get in)# 3. Sono Ready? (entrano solo i Ready)
k get pods -l app=web -o wide

# 4. ¿El Service los tomó?# 4. Did the Service pick them up?# 4. Il Service li ha presi?
k describe svc web    # Endpoints vacío = ahí está el problema# empty Endpoints = there is the problem# Endpoints vuoto = ecco il problema

# 5. Saltear el Service: pegarle al pod directo# 5. Skip the Service: hit the pod directly# 5. Saltare il Service: colpire il pod direttamente
k run t --rm -it --image=nginx -- curl -s <IP-DEL-POD>:8080
★
El paso 5 es el que divide el problema: si la IP del pod responde y la del Service no, el problema es Service/kube-proxy. Si tampoco responde el pod, es la app o el CNI. Bisecás en vez de adivinar.
Step 5 is what splits the problem: if the pod IP answers and the Service IP does not, the problem is Service/kube-proxy. If the pod does not answer either, it is the app or the CNI. You bisect instead of guessing.
Il passo 5 è quello che divide il problema: se l'IP del pod risponde e quello del Service no, il problema è Service/kube-proxy. Se non risponde nemmeno il pod, è l'app o il CNI. Bisezioni invece di indovinare.
Teoría · Cómo funciona de verdad
Theory · How it really works
Teoria · Come funziona davvero

La ClusterIP es ficción

The ClusterIP is fiction

Il ClusterIP è finzione

No hay ninguna interfaz de red con esa IP, ni un proceso escuchando ahí. Es una entrada en las reglas de packet filtering del kernel de cada nodo: cuando un paquete sale hacia esa IP, el kernel le reescribe el destino (DNAT) a la IP de uno de los pods del endpoint. Por eso no podés hacer ping a una ClusterIP.

There is no network interface with that IP, and no process listening on it. It is an entry in each node's kernel packet filtering rules: when a packet leaves for that IP, the kernel rewrites the destination (DNAT) to the IP of one of the endpoint's pods. That is why you cannot ping a ClusterIP.

Non esiste alcuna interfaccia di rete con quell'IP, né un processo in ascolto lì. È una voce nelle regole di packet filtering del kernel di ogni nodo: quando un pacchetto parte verso quell'IP, il kernel ne riscrive la destinazione (DNAT) all'IP di uno dei pod dell'endpoint. Per questo non puoi fare ping a un ClusterIP.

El trabajo de kube-proxy

kube-proxy's job

Il lavoro di kube-proxy

Corre en cada nodo (DaemonSet), observa Services y EndpointSlices en la API, y programa esas reglas. No procesa tráfico: lo configura y se sale del camino. Si muere, lo ya programado sigue funcionando; lo nuevo no se aplica.

It runs on every node (DaemonSet), watches Services and EndpointSlices in the API, and programs those rules. It does not process traffic: it configures and gets out of the way. If it dies, what is already programmed keeps working; new changes are not applied.

Gira su ogni nodo (DaemonSet), osserva Service ed EndpointSlice nell'API, e programma quelle regole. Non processa traffico: lo configura e si toglie di mezzo. Se muore, ciò che è già programmato continua a funzionare; le novità non vengono applicate.

Modos (v1.34)

Modes (v1.34)

Modalità (v1.34)

ModoEstado
ModeStatus
ModalitàStato
iptablesDefault histórico, el más común
iptablesHistoric default, the most common
iptablesDefault storico, il più comune
nftablesGA desde 1.33, mejor a gran escala
nftablesGA since 1.33, better at scale
nftablesGA dalla 1.33, meglio su larga scala
ipvsMás algoritmos de balanceo
ipvsMore balancing algorithms
ipvsPiù algoritmi di bilanciamento

Algunos CNI (Calico, Cilium) pueden reemplazar kube-proxy con eBPF. Para el examen: asumí modo iptables salvo que te digan otra cosa.

Some CNIs (Calico, Cilium) can replace kube-proxy with eBPF. For the exam: assume iptables mode unless told otherwise.

Alcuni CNI (Calico, Cilium) possono sostituire kube-proxy con eBPF. Per l'esame: assumi la modalità iptables salvo indicazione contraria.

Endpoints → EndpointSlices

Endpoints → EndpointSlices

Endpoints → EndpointSlice

El objeto Endpoints original guardaba TODOS los backends en un solo objeto: con miles de pods, cada cambio reescribía todo. EndpointSlice los parte en trozos (100 por defecto). La API Endpoints está deprecada desde v1.33 — sigue respondiendo por compatibilidad, pero lo canónico es EndpointSlice.

The original Endpoints object held ALL backends in one object: with thousands of pods, every change rewrote everything. EndpointSlice splits them into chunks (100 by default). The Endpoints API is deprecated since v1.33 — it still answers for compatibility, but EndpointSlice is canonical.

L'oggetto Endpoints originale teneva TUTTI i backend in un solo oggetto: con migliaia di pod, ogni modifica riscriveva tutto. EndpointSlice li divide in blocchi (100 di default). L'API Endpoints è deprecata dalla v1.33 — risponde ancora per compatibilità, ma il canonico è EndpointSlice.

★
Inconsistencia para cazar: casi todo el material de CKA (y muchos cursos) todavía enseña k get endpoints. Funciona y no te lo van a penalizar, pero si el enunciado dice "EndpointSlice", el objeto que tenés que mirar es ese. Verificalo siempre en la doc oficial de la versión evaluada.
An inconsistency to hunt: almost all CKA material (and many courses) still teaches k get endpoints. It works and will not be penalised, but if the wording says "EndpointSlice", that is the object to look at. Always confirm against the official docs for the version under test.
Un'incoerenza da cacciare: quasi tutto il materiale CKA (e molti corsi) insegna ancora k get endpoints. Funziona e non verrà penalizzato, ma se il testo dice "EndpointSlice", l'oggetto da guardare è quello. Verifica sempre sulla documentazione ufficiale della versione d'esame.
★
Cierre del módulo
Module wrap-up
Chiusura del modulo

Lo que te llevás del Módulo 6

What you take from Module 6

Cosa porti via dal Modulo 6

Resumen · Comandos clave
Summary · Key commands
Riassunto · Comandi chiave
# Crear (el 90% de las veces: expose)# Create (90% of the time: expose)# Creare (il 90% delle volte: expose)
k expose deploy web --port=80 --target-port=8080
k expose deploy web --port=80 --type=NodePort
k run web --image=nginx --port=80 --expose
k create service clusterip s --tcp=80:8080

# Verificar (SIEMPRE, después de crear)# Verify (ALWAYS, after creating)# Verificare (SEMPRE, dopo aver creato)
k get svc -o wide            # muestra SELECTOR# shows SELECTOR# mostra il SELECTOR
k describe svc web            # muestra Endpoints# shows Endpoints# mostra gli Endpoints
k get endpointslices -l kubernetes.io/service-name=web

# Probar desde dentro# Test from inside# Provare da dentro
k run tmp --rm -it --image=nginx -- curl -s web:80
k run dns --rm -it --image=busybox:1.28 -- nslookup web

# Puentes rápidos (debug, no producción)# Quick bridges (debug, not production)# Ponti rapidi (debug, non produzione)
k port-forward svc/web 8080:80
k port-forward pod/web-abc 8080:80

# DNS y proxy# DNS and proxy# DNS e proxy
k get pods -n kube-system -l k8s-app=kube-dns
k get ds -n kube-system kube-proxy

# FQDN: SERVICE.NAMESPACE.svc.cluster.local
Teoría · Lo esencial
Theory · The essentials
Teoria · L'essenziale

Las 5 ideas que no se negocian

The 5 non-negotiable ideas

Le 5 idee non negoziabili

  • El Service no contiene pods: los selecciona por labels. El resultado de esa selección es el EndpointSlice.
  • Sin endpoints = no sirve. Y eso es selector que no matchea, o pods no Ready. Es la primera cosa que verificás.
  • port es del Service, targetPort del container, nodePort del nodo. Tres cosas distintas.
  • Los tipos se anidan: LoadBalancer ⊃ NodePort ⊃ ClusterIP. En bare-metal, LoadBalancer no resuelve.
  • Se habla por nombre, no por IP. Cross-namespace exige el namespace en el FQDN.
  • A Service does not contain pods: it selects them by label. The result of that selection is the EndpointSlice.
  • No endpoints = no service. And that means a selector that does not match, or pods not Ready. It is the first thing you check.
  • port belongs to the Service, targetPort to the container, nodePort to the node. Three different things.
  • The types nest: LoadBalancer ⊃ NodePort ⊃ ClusterIP. On bare metal, LoadBalancer never resolves.
  • You address by name, not IP. Cross-namespace requires the namespace in the FQDN.
  • Un Service non contiene pod: li seleziona per label. Il risultato di quella selezione è l'EndpointSlice.
  • Niente endpoint = niente servizio. E significa un selector che non corrisponde, o pod non Ready. È la prima cosa da verificare.
  • port è del Service, targetPort del container, nodePort del nodo. Tre cose diverse.
  • I tipi si annidano: LoadBalancer ⊃ NodePort ⊃ ClusterIP. Su bare metal, LoadBalancer non risolve mai.
  • Si parla per nome, non per IP. Il cross-namespace richiede il namespace nell'FQDN.
★
El hilo del módulo: el Service es indirección por labels — el mismo patrón del Deployment sobre los pods (M4). Kubernetes casi nunca referencia por nombre o IP; referencia por selector. Interiorizá eso y la mitad del troubleshooting se vuelve mecánico.
The thread of the module: a Service is indirection by labels — the same pattern as a Deployment over pods (M4). Kubernetes almost never references by name or IP; it references by selector. Internalise that and half of troubleshooting becomes mechanical.
Il filo del modulo: un Service è indirezione per label — lo stesso pattern del Deployment sui pod (M4). Kubernetes non referenzia quasi mai per nome o IP; referenzia per selector. Interiorizzalo e metà del troubleshooting diventa meccanico.
Checkpoint Módulo 6: Services (los 4 tipos + headless), la relación selector→endpoints, CoreDNS y el FQDN, y el rol de kube-proxy. Mitad del dominio Services & Networking (20%). Siguiente: Módulo 7 — Ingress, Gateway API y NetworkPolicies.
Module 6 checkpoint: Services (the 4 types + headless), the selector→endpoints relationship, CoreDNS and the FQDN, and kube-proxy's role. Half of the Services & Networking domain (20%). Next: Module 7 — Ingress, Gateway API and NetworkPolicies.
Checkpoint Modulo 6: Service (i 4 tipi + headless), la relazione selector→endpoint, CoreDNS e l'FQDN, e il ruolo di kube-proxy. Metà del dominio Services & Networking (20%). Prossimo: Modulo 7 — Ingress, Gateway API e NetworkPolicy.
★
Fase 2 · resolver en vivo
Phase 2 · solve it live
Fase 2 · risolvere dal vivo

Práctica — 9 ejercicios

Practice — 9 exercises

Pratica — 9 esercizi

Cinco de construcción, cuatro de troubleshooting. Todo se verifica por endpoints.
Five building, four troubleshooting. Everything is verified through endpoints.
Cinque di costruzione, quattro di troubleshooting. Tutto si verifica tramite gli endpoint.
0 / 9
◆
Manifests publicados. Cada ejercicio tiene su YAML servido por este mismo sitio: k apply -f <url>/manifests/m6e1.yaml. Los E son la solución de referencia; los T plantan el problema — aplicalos y diagnosticá sin leerlos. Todos crean el namespace net y k delete -f <misma-url> los limpia. Excepción: T3, cuyo manifest solo arma el escenario — la rotura toca kube-system y va a mano, porque un YAML público que te deje el cluster entero sin DNS es un pie de plomo. Cada tarjeta trae el comando exacto, con botón de copiar.
Published manifests. Every exercise has its YAML served by this very site: k apply -f <url>/manifests/m6e1.yaml. The E ones are the reference solution; the T ones plant the problem — apply them and diagnose without reading them. All create namespace net and k delete -f <same-url> cleans up. Exception: T3, whose manifest only sets the scene — the break touches kube-system and is done by hand, because a public YAML that leaves your whole cluster without DNS is a footgun. Each card carries the exact command, with a copy button.
Manifest pubblicati. Ogni esercizio ha il suo YAML servito da questo stesso sito: k apply -f <url>/manifests/m6e1.yaml. Gli E sono la soluzione di riferimento; i T piantano il problema — applicali e diagnostica senza leggerli. Tutti creano il namespace net e k delete -f <stessa-url> pulisce. Eccezione: il T3, il cui manifest prepara solo lo scenario — la rottura tocca kube-system e si fa a mano, perché uno YAML pubblico che ti lascia l'intero cluster senza DNS è un'arma puntata al piede. Ogni scheda porta il comando esatto, con pulsante copia.
🧠
Modelo mental. Service = selector + puertos → EndpointSlice. Cada ejercicio termina en la misma pregunta: ¿tiene endpoints? Si la respuesta es no, ya sabés que es el selector o la readiness. Nunca "arregles" adivinando: mirá primero describe svc.
Mental model. Service = selector + ports → EndpointSlice. Every exercise ends at the same question: does it have endpoints? If the answer is no, you already know it is the selector or readiness. Never "fix" by guessing: look at describe svc first.
Modello mentale. Service = selector + porte → EndpointSlice. Ogni esercizio finisce alla stessa domanda: ha endpoint? Se la risposta è no, sai già che è il selector o la readiness. Non "aggiustare" a indovinare: guarda prima describe svc.
◆
Preparación. Nada de esto rompe el cluster. Trabajá en un namespace descartable: k create ns net && k config set-context --current -n net, y al final k delete ns net. Para T3 sí conviene un snapshot: se toca CoreDNS.
Setup. None of this breaks the cluster. Work in a throwaway namespace: k create ns net && k config set-context --current -n net, and at the end k delete ns net. For T3 a snapshot is worth having: it touches CoreDNS.
Preparazione. Nulla di questo rompe il cluster. Lavora in un namespace usa e getta: k create ns net && k config set-context --current -n net, e alla fine k delete ns net. Per T3 conviene uno snapshot: si tocca CoreDNS.
E1

Del deployment al Service, verificando

From deployment to Service, verified

Dal deployment al Service, verificando

~5 min

Creá un Deployment web (nginx, 3 réplicas) y exponelo como ClusterIP en el puerto 80. Después probá, en este orden: que el Service existe, que tiene 3 endpoints, y que responde desde otro pod por nombre. Finalmente borrá un pod y verificá que el EndpointSlice se actualiza solo.

Create a Deployment web (nginx, 3 replicas) and expose it as ClusterIP on port 80. Then check, in this order: the Service exists, it has 3 endpoints, and it answers from another pod by name. Finally delete a pod and verify the EndpointSlice updates on its own.

Crea un Deployment web (nginx, 3 repliche) ed esponilo come ClusterIP sulla porta 80. Poi verifica, in quest'ordine: il Service esiste, ha 3 endpoint, e risponde da un altro pod per nome. Infine cancella un pod e verifica che l'EndpointSlice si aggiorni da solo.

Ver soluciónShow solutionMostra soluzione
manifest · soluciónmanifest · solutionmanifest · soluzione
k create deploy web --image=nginx --replicas=3
k expose deploy web --port=80

k get svc web -o wide                # mirá la columna SELECTOR# look at the SELECTOR column# guarda la colonna SELECTOR
k describe svc web | grep -i endpoints
k get endpointslices -l kubernetes.io/service-name=web

k run tmp --rm -it --image=nginx -- curl -s web:80

k delete pod -l app=web --field-selector=status.phase=Running --wait=false
k get endpointslices -l kubernetes.io/service-name=web -o wide
Claves
Key points
Punti chiave
  • expose hereda el selector del Deployment, así que los endpoints salen bien de una: es la razón por la que casi siempre se prefiere sobre create service.
  • El EndpointSlice se recalcula solo cuando los pods cambian: es un controller observando labels, no una lista que mantengas vos.
  • Verificar por endpoints, no por "se creó el objeto". Un Service se crea siempre, aunque no sirva a nadie.
  • expose inherits the Deployment's selector, so endpoints come out right first time: that is why it is nearly always preferred over create service.
  • The EndpointSlice recalculates itself when pods change: it is a controller watching labels, not a list you maintain.
  • Verify by endpoints, not by "the object was created". A Service is always created, even when it serves nobody.
  • expose eredita il selector del Deployment, quindi gli endpoint escono giusti al primo colpo: per questo si preferisce quasi sempre a create service.
  • L'EndpointSlice si ricalcola da solo quando i pod cambiano: è un controller che osserva le label, non una lista che mantieni tu.
  • Verifica per endpoint, non per "l'oggetto è stato creato". Un Service viene sempre creato, anche se non serve nessuno.
E2

port vs targetPort: el que conecta pero falla

port vs targetPort: it connects but fails

port contro targetPort: si connette ma fallisce

~5 min

Creá un Deployment api con la imagen hashicorp/http-echo, argumentos -text=hola y -listen=:5678. Exponelo de forma que se le pueda pegar en el puerto 80 del Service. Primero hacelo mal a propósito (sin --target-port) y observá el síntoma; después corregilo.

Create a Deployment api with the image hashicorp/http-echo, args -text=hola and -listen=:5678. Expose it so it can be hit on the Service's port 80. First do it wrong on purpose (no --target-port) and observe the symptom; then fix it.

Crea un Deployment api con l'immagine hashicorp/http-echo, argomenti -text=hola e -listen=:5678. Esponilo in modo da poterlo colpire sulla porta 80 del Service. Prima fallo sbagliato di proposito (senza --target-port) e osserva il sintomo; poi correggilo.

Ver soluciónShow solutionMostra soluzione
manifest · soluciónmanifest · solutionmanifest · soluzione
k create deploy api --image=hashicorp/http-echo -- -text=hola -listen=:5678

# MAL: targetPort asume 80, pero la app escucha en 5678# WRONG: targetPort assumes 80, but the app listens on 5678# SBAGLIATO: targetPort assume 80, ma l'app ascolta su 5678
k expose deploy api --port=80
k run t --rm -it --image=nginx -- curl -s --max-time 5 api:80
#   cuelga y muere por timeout — y el Service TIENE endpoints#   hangs and dies on timeout — and the Service DOES have endpoints#   si blocca e muore in timeout — e il Service HA endpoint

# BIEN# RIGHT# GIUSTO
k delete svc api
k expose deploy api --port=80 --target-port=5678
k run t --rm -it --image=nginx -- curl -s api:80    #  hola
Claves
Key points
Punti chiave
  • El síntoma distingue el diagnóstico. Selector mal = cero endpoints. targetPort mal = endpoints correctos pero timeout. Si ves endpoints y no anda, mirá los puertos.
  • Sin --target-port, kubectl asume targetPort = port. Es el default más traicionero del módulo.
  • Alternativa robusta: nombrá el containerPort (name: http) y usá targetPort: http.
  • The symptom tells the diagnosis apart. Wrong selector = zero endpoints. Wrong targetPort = correct endpoints but timeouts. If you see endpoints and it still fails, look at the ports.
  • Without --target-port, kubectl assumes targetPort = port. The most treacherous default in the module.
  • Robust alternative: name the containerPort (name: http) and use targetPort: http.
  • Il sintomo distingue la diagnosi. Selector sbagliato = zero endpoint. targetPort sbagliato = endpoint corretti ma timeout. Se vedi endpoint e non va, guarda le porte.
  • Senza --target-port, kubectl assume targetPort = port. Il default più insidioso del modulo.
  • Alternativa robusta: dai un nome al containerPort (name: http) e usa targetPort: http.
E3

NodePort con puerto fijo (generá y editá)

NodePort with a pinned port (generate and edit)

NodePort con porta fissa (genera e modifica)

~5 min

Exponé el Deployment web como NodePort en el puerto 30080 exacto. Probalo desde tu máquina contra la IP de un worker que no tenga pods de web, y explicá por qué igual funciona. Después confirmá que el ClusterIP sigue vivo.

Expose the web Deployment as NodePort on the exact port 30080. Test it from your machine against the IP of a worker that has no web pods, and explain why it still works. Then confirm the ClusterIP is still alive.

Esponi il Deployment web come NodePort sulla porta 30080 esatta. Provalo dalla tua macchina contro l'IP di un worker che non ha pod di web, e spiega perché funziona lo stesso. Poi conferma che il ClusterIP è ancora vivo.

Ver soluciónShow solutionMostra soluzione
manifest · soluciónmanifest · solutionmanifest · soluzione
# expose no tiene flag para nodePort fijo → generá y editá# expose has no flag for a pinned nodePort → generate and edit# expose non ha un flag per il nodePort fisso → genera e modifica
k expose deploy web --port=80 --type=NodePort --name=web-np $do > np.yaml
vim np.yaml        # en ports[0]: nodePort: 30080# in ports[0]: nodePort: 30080# in ports[0]: nodePort: 30080
k apply -f np.yaml

k get nodes -o wide
k get pods -l app=web -o wide    # elegí un nodo SIN pods# pick a node WITHOUT pods# scegli un nodo SENZA pod
curl http://<IP-DE-ESE-NODO>:30080

k run t --rm -it --image=nginx -- curl -s web-np:80   # el ClusterIP sigue# ClusterIP still works# il ClusterIP funziona ancora
Claves
Key points
Punti chiave
  • Funciona en cualquier nodo porque kube-proxy programa las reglas en todos los nodos: el que recibe reenvía al pod, esté donde esté.
  • Los tipos se anidan. Un NodePort sigue teniendo su ClusterIP y su nombre DNS: no reemplazaste nada, agregaste una capa.
  • El patrón "generá con $do, editá una línea, aplicá" resuelve todo lo que no tiene flag. Es más rápido que escribir el YAML entero.
  • It works on any node because kube-proxy programs the rules on every node: whichever receives it forwards to the pod, wherever that is.
  • The types nest. A NodePort still has its ClusterIP and DNS name: you replaced nothing, you added a layer.
  • The "generate with $do, edit one line, apply" pattern covers everything that has no flag. Faster than writing the whole YAML.
  • Funziona su qualsiasi nodo perché kube-proxy programma le regole su tutti i nodi: quello che riceve inoltra al pod, ovunque sia.
  • I tipi si annidano. Un NodePort mantiene il suo ClusterIP e il nome DNS: non hai sostituito nulla, hai aggiunto uno strato.
  • Il pattern "genera con $do, modifica una riga, applica" copre tutto ciò che non ha un flag. Più rapido che scrivere l'intero YAML.
E4

Headless: DNS que devuelve pods

Headless: DNS that returns pods

Headless: DNS che restituisce pod

~6 min

Creá un Service headless web-h apuntando a los pods de web. Desde un pod, comparativamente: nslookup web y nslookup web-h. Explicá la diferencia en la salida. Extra: creá un StatefulSet db de 2 réplicas con su headless y resolvé db-0 por nombre.

Create a headless Service web-h pointing at the web pods. From a pod, compare: nslookup web and nslookup web-h. Explain the difference in the output. Extra: create a 2-replica StatefulSet db with its headless Service and resolve db-0 by name.

Crea un Service headless web-h che punti ai pod di web. Da un pod, confronta: nslookup web e nslookup web-h. Spiega la differenza nell'output. Extra: crea uno StatefulSet db di 2 repliche col suo headless e risolvi db-0 per nome.

Ver soluciónShow solutionMostra soluzione
manifest · soluciónmanifest · solutionmanifest · soluzione
k expose deploy web --port=80 --name=web-h $do > h.yaml
vim h.yaml          # en spec:  clusterIP: None# under spec:  clusterIP: None# sotto spec:  clusterIP: None
k apply -f h.yaml
k get svc                        # web-h tiene CLUSTER-IP None# web-h has CLUSTER-IP None# web-h ha CLUSTER-IP None

k run dns --rm -it --image=busybox:1.28 -- sh
#   nslookup web     -> 1 dirección: la VIP 10.96.x.x#   nslookup web     -> 1 address: the VIP 10.96.x.x#   nslookup web     -> 1 indirizzo: la VIP 10.96.x.x
#   nslookup web-h   -> 3 direcciones: las IPs de los pods#   nslookup web-h   -> 3 addresses: the pod IPs#   nslookup web-h   -> 3 indirizzi: gli IP dei pod

# StatefulSet: cada pod tiene nombre DNS propio y estable# StatefulSet: each pod has its own stable DNS name# StatefulSet: ogni pod ha un nome DNS proprio e stabile
nslookup db-0.db.net.svc.cluster.local
Claves
Key points
Punti chiave
  • clusterIP: None es lo único que lo vuelve headless. Sigue teniendo selector y endpoints — lo que no tiene es VIP ni balanceo.
  • El cliente elige la instancia. Por eso es la base de los StatefulSets: sin identidad por pod, una réplica de base de datos no sirve.
  • Patrón de nombre: POD-N.SERVICIO.NAMESPACE.svc.cluster.local. Solo existe con un Service headless.
  • clusterIP: None is the only thing making it headless. It still has a selector and endpoints — what it lacks is a VIP and balancing.
  • The client picks the instance. That is why it underpins StatefulSets: without per-pod identity, a database replica is useless.
  • Name pattern: POD-N.SERVICE.NAMESPACE.svc.cluster.local. It only exists with a headless Service.
  • clusterIP: None è l'unica cosa che lo rende headless. Ha ancora selector ed endpoint — ciò che manca è la VIP e il bilanciamento.
  • Il client sceglie l'istanza. Per questo è la base degli StatefulSet: senza identità per pod, una replica di database è inutile.
  • Schema del nome: POD-N.SERVICE.NAMESPACE.svc.cluster.local. Esiste solo con un Service headless.
E5

DNS cross-namespace y ExternalName

Cross-namespace DNS and ExternalName

DNS cross-namespace ed ExternalName

~6 min

Con web en el namespace net, levantá un pod cliente en otro e intentá curl web. Falla: arreglalo sin tocar el Service. Después creá un ExternalName externo que apunte a example.com y resolvelo desde un pod. ¿Qué tipo de registro DNS devuelve?

With web in the net namespace, start a client pod in otro and try curl web. It fails: fix it without touching the Service. Then create an ExternalName externo pointing at example.com and resolve it from a pod. What kind of DNS record comes back?

Con web nel namespace net, avvia un pod client in otro e prova curl web. Fallisce: sistemalo senza toccare il Service. Poi crea un ExternalName externo che punti a example.com e risolvilo da un pod. Che tipo di record DNS restituisce?

Ver soluciónShow solutionMostra soluzione
manifest · soluciónmanifest · solutionmanifest · soluzione
k create ns otro
k run t -n otro --rm -it --image=nginx -- curl -s --max-time 5 web
#   falla: busca web.otro.svc..., no web.net.svc...#   fails: it looks up web.otro.svc..., not web.net.svc...#   fallisce: cerca web.otro.svc..., non web.net.svc...

k run t -n otro --rm -it --image=nginx -- curl -s web.net        #  OK
k run t -n otro --rm -it --image=nginx -- curl -s web.net.svc.cluster.local

k create service externalname externo --external-name=example.com
k run dns --rm -it --image=busybox:1.28 -- nslookup externo
#   devuelve un CNAME a example.com: sin ClusterIP, sin endpoints, sin proxy#   returns a CNAME to example.com: no ClusterIP, no endpoints, no proxying#   restituisce un CNAME a example.com: nessun ClusterIP, nessun endpoint, nessun proxy
Claves
Key points
Punti chiave
  • El nombre corto usa los search domains del pod, que empiezan por su propio namespace. Cross-namespace exige al menos servicio.namespace.
  • Es una de las causas más frecuentes del "no le puedo hablar al otro servicio" en el examen, y no deja ningún error en logs: solo un DNS que no resuelve.
  • ExternalName no es un proxy: es puro DNS. No tiene ClusterIP ni endpoints, y el tráfico nunca pasa por Kubernetes.
  • The short name uses the pod's search domains, which begin with its own namespace. Cross-namespace needs at least service.namespace.
  • It is one of the most frequent causes of "I cannot reach the other service" in the exam, and it leaves no error in logs: just DNS that does not resolve.
  • ExternalName is not a proxy: it is pure DNS. No ClusterIP, no endpoints, and traffic never goes through Kubernetes.
  • Il nome breve usa i search domain del pod, che iniziano dal suo namespace. Il cross-namespace richiede almeno service.namespace.
  • È una delle cause più frequenti del "non riesco a raggiungere l'altro servizio" all'esame, e non lascia alcun errore nei log: solo un DNS che non risolve.
  • ExternalName non è un proxy: è puro DNS. Nessun ClusterIP, nessun endpoint, e il traffico non passa mai da Kubernetes.
T1

Troubleshooting — cero endpoints por selector

Troubleshooting — zero endpoints, bad selector

Troubleshooting — zero endpoint, selector sbagliato

~6 min

Un Service shop existe, tiene ClusterIP, y curl shop desde otro pod muere por timeout sin ningún error en los logs de la app. Encontrá la causa y arreglala sin borrar el Service.

A Service shop exists, has a ClusterIP, and curl shop from another pod dies on timeout with no error in the app logs. Find the cause and fix it without deleting the Service.

Un Service shop esiste, ha un ClusterIP, e curl shop da un altro pod muore in timeout senza alcun errore nei log dell'app. Trova la causa e sistemala senza cancellare il Service.

manifest · plantar el problemamanifest · plant the problemmanifest · piantare il problema
Ver soluciónShow solutionMostra soluzione

Equivalente imperativo: k create deploy tienda --image=nginx + k create service clusterip shop --tcp=80:80 — create service se inventa el selector app=shop.

Imperative equivalent: k create deploy tienda --image=nginx + k create service clusterip shop --tcp=80:80 — create service invents the selector app=shop.

Equivalente imperativo: k create deploy tienda --image=nginx + k create service clusterip shop --tcp=80:80 — create service si inventa il selector app=shop.

k describe svc shop | grep -iE 'selector|endpoints'
#   Selector: app=shop   ·   Endpoints: <none>   ← ahí está#   Selector: app=shop   ·   Endpoints: <none>   ← there it is#   Selector: app=shop   ·   Endpoints: <none>   ← eccolo

k get pods -l app=shop            # no hay ninguno# none at all# nessuno
k get pods --show-labels          # los pods dicen app=tienda# the pods say app=tienda# i pod dicono app=tienda

# dos formas de arreglarlo; la primera es la más limpia# two ways to fix it; the first is cleanest# due modi per sistemarlo; il primo è il più pulito
k set selector svc shop app=tienda
#   o: k patch svc shop -p '{"spec":{"selector":{"app":"tienda"}}}'#   or: k patch svc shop -p '{"spec":{"selector":{"app":"tienda"}}}'#   oppure: k patch svc shop -p '{"spec":{"selector":{"app":"tienda"}}}'

k describe svc shop | grep -i endpoints   # ahora sí# now it is populated# ora è popolato
Claves
Key points
Punti chiave
  • Falla en silencio. El Service se crea, tiene IP, el DNS resuelve — y no hay nadie detrás. Ningún log de la app va a mencionarlo: la app nunca recibe la conexión.
  • create service se inventa el selector app=<nombre-del-service>. Por eso expose es el camino por defecto.
  • --show-labels es el comando que resuelve este caso en 5 segundos. Tenelo a mano.
  • It fails silently. The Service is created, has an IP, DNS resolves — and there is nobody behind it. No app log will mention it: the app never receives the connection.
  • create service invents the selector app=<service-name>. That is why expose is the default path.
  • --show-labels is the command that cracks this in 5 seconds. Keep it handy.
  • Fallisce in silenzio. Il Service viene creato, ha un IP, il DNS risolve — e dietro non c'è nessuno. Nessun log dell'app lo menzionerà: l'app non riceve mai la connessione.
  • create service si inventa il selector app=<nome-del-service>. Per questo expose è la strada di default.
  • --show-labels è il comando che risolve questo caso in 5 secondi. Tienilo a portata.
T2

Troubleshooting — la readinessProbe que vacía el Service

Troubleshooting — the readinessProbe that empties the Service

Troubleshooting — la readinessProbe che svuota il Service

~6 min

El selector del Service es correcto y los pods están Running, pero el Service no tiene endpoints. Diagnosticá y arreglá.

The Service selector is correct and the pods are Running, but the Service has no endpoints. Diagnose and fix.

Il selector del Service è corretto e i pod sono Running, ma il Service non ha endpoint. Diagnostica e sistema.

manifest · plantar el problemamanifest · plant the problemmanifest · piantare il problema
Ver soluciónShow solutionMostra soluzione

Equivalente imperativo: agregarle al deployment una readinessProbe HTTP contra /healthz en el puerto 80 — nginx no sirve esa ruta.

Imperative equivalent: add an HTTP readinessProbe against /healthz on port 80 to the deployment — nginx does not serve that path.

Equivalente imperativo: aggiungere al deployment una readinessProbe HTTP verso /healthz sulla porta 80 — nginx non serve quel path.

k get pods -l app=front
#   READY 0/1 pero STATUS Running ← la pista está en READY, no en STATUS#   READY 0/1 but STATUS Running ← the clue is in READY, not STATUS#   READY 0/1 ma STATUS Running ← l'indizio è in READY, non in STATUS

k describe pod <pod> | grep -A5 -i readiness
k describe pod <pod> | tail -20
#   Warning  Unhealthy  Readiness probe failed: HTTP probe returned 404

# arreglar la ruta (o el puerto) de la probe# fix the probe's path (or port)# sistemare il path (o la porta) della probe
k edit deploy front        # path: /healthz  →  /# path: /healthz  →  /# path: /healthz  →  /

k get pods -l app=front                              #  1/1
k describe svc front | grep -i endpoints            #  poblado#  populated#  popolato
Claves
Key points
Punti chiave
  • Running ≠ Ready. La columna que importa para el Service es READY: solo los Ready entran al EndpointSlice.
  • Los Events del describe pod te dicen exactamente por qué falla la probe (código HTTP, connection refused, timeout).
  • Es el mismo síntoma que T1 (cero endpoints) con causa distinta. Por eso el orden del diagnóstico importa: primero selector, después readiness.
  • Running ≠ Ready. The column that matters to the Service is READY: only Ready pods enter the EndpointSlice.
  • The Events in describe pod tell you exactly why the probe fails (HTTP code, connection refused, timeout).
  • It is the same symptom as T1 (zero endpoints) with a different cause. That is why diagnostic order matters: selector first, readiness second.
  • Running ≠ Ready. La colonna che conta per il Service è READY: solo i Ready entrano nell'EndpointSlice.
  • Gli Events del describe pod dicono esattamente perché la probe fallisce (codice HTTP, connection refused, timeout).
  • È lo stesso sintomo di T1 (zero endpoint) con causa diversa. Per questo l'ordine diagnostico conta: prima il selector, poi la readiness.
T3

Troubleshooting — el DNS del cluster no resuelve

Troubleshooting — cluster DNS does not resolve

Troubleshooting — il DNS del cluster non risolve

~7 min

Ningún pod resuelve nombres: curl web da could not resolve host, pero curl <ClusterIP> anda perfecto. Diagnosticá siguiendo la cadena completa y arreglá.

Para plantarlo: el manifest solo deja el blanco armado; la rotura va a mano, porque toca kube-system: k -n kube-system scale deploy coredns --replicas=0. Snapshot antes, y para restaurar --replicas=2.

No pod resolves names: curl web gives could not resolve host, but curl <ClusterIP> works fine. Diagnose along the full chain and fix.

To plant it: the manifest only sets up the target; the break is done by hand, because it touches kube-system: k -n kube-system scale deploy coredns --replicas=0. Snapshot first, and restore with --replicas=2.

Nessun pod risolve i nomi: curl web dà could not resolve host, ma curl <ClusterIP> funziona benissimo. Diagnostica lungo tutta la catena e sistema.

Per prepararlo: il manifest prepara solo il bersaglio; la rottura si fa a mano, perché tocca kube-system: k -n kube-system scale deploy coredns --replicas=0. Prima lo snapshot, e per ripristinare --replicas=2.

manifest · armar el escenariomanifest · set the scenemanifest · preparare lo scenario
Ver soluciónShow solutionMostra soluzione
# el hecho clave: por IP funciona, por nombre no → es DNS, no red# the key fact: by IP it works, by name it does not → it is DNS, not networking# il fatto chiave: per IP funziona, per nome no → è DNS, non rete

# 1 · ¿corren los pods de CoreDNS?# 1 · are the CoreDNS pods running?# 1 · i pod di CoreDNS girano?
k get pods -n kube-system -l k8s-app=kube-dns     # ninguno# none# nessuno

# 2 · ¿el Service kube-dns tiene endpoints?# 2 · does the kube-dns Service have endpoints?# 2 · il Service kube-dns ha endpoint?
k -n kube-system describe svc kube-dns | grep -i endpoints

# 3 · ¿el pod apunta al nameserver correcto?# 3 · does the pod point at the right nameserver?# 3 · il pod punta al nameserver giusto?
k exec <pod> -- cat /etc/resolv.conf        #  nameserver 10.96.0.10

# 4 · arreglar y reverificar# 4 · fix and re-verify# 4 · sistemare e riverificare
k -n kube-system scale deploy coredns --replicas=2
k run dns --rm -it --image=busybox:1.28 -- nslookup web
Claves
Key points
Punti chiave
  • "Por IP sí, por nombre no" divide el problema al instante: la red está bien, el que falla es el DNS. Ese contraste es el primer test que hacés siempre.
  • La cadena de DNS tiene 3 eslabones: pods de CoreDNS → Service kube-dns con endpoints → resolv.conf del pod. Se revisan en ese orden.
  • CoreDNS es un Deployment normal: se diagnostica con logs, describe y get cm coredns como cualquier app. Un Corefile roto también se ve en sus logs.
  • Recordá que sin CNI no hay red de pods, y sin red de pods CoreDNS queda Pending: es la variante de este mismo problema que ya viviste al armar el cluster.
  • "By IP yes, by name no" splits the problem instantly: networking is fine, DNS is what fails. That contrast is the first test you always run.
  • The DNS chain has 3 links: CoreDNS pods → kube-dns Service with endpoints → the pod's resolv.conf. Check them in that order.
  • CoreDNS is an ordinary Deployment: diagnose it with logs, describe and get cm coredns like any app. A broken Corefile shows up in its logs too.
  • Remember that without a CNI there is no pod network, and without a pod network CoreDNS stays Pending: the variant of this same problem you already lived while building the cluster.
  • "Per IP sì, per nome no" divide il problema all'istante: la rete è a posto, a fallire è il DNS. Quel contrasto è il primo test che fai sempre.
  • La catena DNS ha 3 anelli: pod di CoreDNS → Service kube-dns con endpoint → resolv.conf del pod. Si controllano in quest'ordine.
  • CoreDNS è un Deployment normale: si diagnostica con logs, describe e get cm coredns come qualsiasi app. Anche un Corefile rotto si vede nei suoi log.
  • Ricorda che senza CNI non c'è rete dei pod, e senza rete dei pod CoreDNS resta Pending: è la variante di questo stesso problema che hai già vissuto costruendo il cluster.
T4

Troubleshooting — el pod que no resuelve, con el DNS sano

Troubleshooting — the pod that will not resolve, with DNS healthy

Troubleshooting — il pod che non risolve, col DNS sano

~6 min

Dos clientes con la misma imagen en el mismo namespace: cliente-a resuelve web y cliente-b no. CoreDNS está perfecto y el resto del cluster también. Encontrá la diferencia y arreglá cliente-b.

Antes de tocar nada, hacé una prueba más desde cliente-b: probá resolver un nombre de internet. La respuesta cambia todo el diagnóstico.

Two clients with the same image in the same namespace: cliente-a resolves web and cliente-b does not. CoreDNS is perfectly healthy and so is the rest of the cluster. Find the difference and fix cliente-b.

Before touching anything, run one more test from cliente-b: try resolving an internet name. The answer changes the whole diagnosis.

Due client con la stessa immagine nello stesso namespace: cliente-a risolve web e cliente-b no. CoreDNS è perfettamente sano e anche il resto del cluster. Trova la differenza e sistema cliente-b.

Prima di toccare qualsiasi cosa, fai un'altra prova da cliente-b: prova a risolvere un nome di internet. La risposta cambia tutta la diagnosi.

manifest · plantar el problemamanifest · plant the problemmanifest · piantare il problema
Ver soluciónShow solutionMostra soluzione
k exec deploy/cliente-a -- curl -s --max-time 5 web     # anda# works# funziona
k exec deploy/cliente-b -- curl -s --max-time 5 web        # could not resolve host
k exec deploy/cliente-b -- curl -sI --max-time 5 example.com
#   ¡SÍ resuelve internet! → el DNS del pod anda, pero no es el del cluster#   it DOES resolve the internet! → the pod's DNS works, just not the cluster's#   risolve internet! → il DNS del pod funziona, ma non è quello del cluster

# comparar el resolv.conf de los dos: ahí está todo# compare both resolv.conf files: everything is there# confrontare i due resolv.conf: è tutto lì
k exec deploy/cliente-a -- cat /etc/resolv.conf
#   nameserver 10.96.0.10        search net.svc.cluster.local ...   ndots:5
k exec deploy/cliente-b -- cat /etc/resolv.conf
#   el nameserver del NODO, sin search domains del cluster#   the NODE's nameserver, with no cluster search domains#   il nameserver del NODO, senza i search domain del cluster

k get deploy cliente-b -o jsonpath='{.spec.template.spec.dnsPolicy}'; echo
#   Default   <- el culpable

# arreglo: volver al DNS del cluster# fix: go back to cluster DNS# fix: tornare al DNS del cluster
k patch deploy cliente-b -p '{"spec":{"template":{"spec":{"dnsPolicy":"ClusterFirst"}}}}'
k rollout status deploy/cliente-b
k exec deploy/cliente-b -- curl -s web
Claves
Key points
Punti chiave
  • El nombre del campo miente: dnsPolicy: Default NO es el default. El default real es ClusterFirst. Default significa "heredá el resolv.conf del nodo", que no conoce el DNS del cluster.
  • Resolver internet pero no servicios internos es la firma exacta de este caso. Si CoreDNS estuviera caído (T3) no resolvería nada; si fuera una NetworkPolicy de egress, tampoco. Que ande lo de afuera y falle lo de adentro apunta al resolv.conf del pod, no al servidor.
  • Un solo pod afectado y el resto sano ⇒ el problema es del pod. Este contraste es el que te ahorra ir a mirar kube-system: T3 se diagnostica hacia el servidor, T4 hacia el cliente.
  • Comparar el resolv.conf de un pod sano contra el del roto es el atajo del ejercicio. Las tres cosas que mirás son nameserver, search y ndots.
  • The field name lies: dnsPolicy: Default is NOT the default. The real default is ClusterFirst. Default means "inherit the node's resolv.conf", which knows nothing about cluster DNS.
  • Resolving the internet but not internal services is this case's exact signature. If CoreDNS were down (T3) nothing would resolve; nor would it with an egress NetworkPolicy. Outside working and inside failing points at the pod's resolv.conf, not at the server.
  • One pod affected and the rest healthy ⇒ the problem belongs to the pod. That contrast is what saves you a trip to kube-system: T3 is diagnosed towards the server, T4 towards the client.
  • Comparing a healthy pod's resolv.conf against the broken one is the exercise's shortcut. The three things to read are nameserver, search and ndots.
  • Il nome del campo mente: dnsPolicy: Default NON è il default. Il default vero è ClusterFirst. Default significa "eredita il resolv.conf del nodo", che non conosce il DNS del cluster.
  • Risolvere internet ma non i servizi interni è la firma esatta di questo caso. Se CoreDNS fosse caduto (T3) non risolverebbe nulla; nemmeno con una NetworkPolicy di egress. Che funzioni il fuori e fallisca il dentro punta al resolv.conf del pod, non al server.
  • Un solo pod colpito e il resto sano ⇒ il problema è del pod. Questo contrasto ti risparmia il giro in kube-system: il T3 si diagnostica verso il server, il T4 verso il client.
  • Confrontare il resolv.conf di un pod sano con quello rotto è la scorciatoia dell'esercizio. Le tre cose da leggere sono nameserver, search e ndots.

Autoevaluación — antes de marcar M6 como ★ dominado

Self-check — before marking M6 as ★ mastered

Autovalutazione — prima di segnare M6 come ★ padroneggiato

  • Exponer un Deployment y verificar endpoints en menos de 1 min.
  • Explicar la diferencia entre port, targetPort y nodePort sin dudar.
  • Fijar un nodePort concreto usando $do + editar.
  • Explicar por qué un NodePort responde en un nodo sin pods.
  • Crear un headless y decir qué devuelve su DNS.
  • Escribir el FQDN completo de un Service de memoria.
  • Diagnosticar cero endpoints distinguiendo selector de readiness.
  • Diagnosticar un fallo de DNS recorriendo los 3 eslabones.
  • Expose a Deployment and verify endpoints in under 1 min.
  • Explain the difference between port, targetPort and nodePort without hesitating.
  • Pin a specific nodePort using $do + edit.
  • Explain why a NodePort answers on a node with no pods.
  • Create a headless Service and say what its DNS returns.
  • Write a Service's full FQDN from memory.
  • Diagnose zero endpoints, telling selector apart from readiness.
  • Diagnose a DNS failure along the 3 links.
  • Esporre un Deployment e verificare gli endpoint in meno di 1 min.
  • Spiegare la differenza fra port, targetPort e nodePort senza esitare.
  • Fissare un nodePort specifico usando $do + modifica.
  • Spiegare perché un NodePort risponde su un nodo senza pod.
  • Creare un Service headless e dire cosa restituisce il suo DNS.
  • Scrivere l'FQDN completo di un Service a memoria.
  • Diagnosticare zero endpoint distinguendo selector da readiness.
  • Diagnosticare un guasto DNS percorrendo i 3 anelli.
Módulo 6 completado · Services & Networking, parte 1 de 2 · Siguiente: Ingress, Gateway API y NetworkPolicies
Module 6 complete · Services & Networking, part 1 of 2 · Next: Ingress, Gateway API and NetworkPolicies
Modulo 6 completato · Services & Networking, parte 1 di 2 · Prossimo: Ingress, Gateway API e NetworkPolicy