Pods are born and die with different IPs. No serious client will keep track of that. Service gives a stable name and IP; Ingress provides an HTTP(S) entry point; DNS resolves names; TLS protects the path.
Course seal: tested on Kubernetes 1.35, ingress-nginx, and cert-manager.
Service: the stable name
A Service selects pods by label and balances traffic.
apiVersion: v1
kind: Service
metadata:
name: api
namespace: portal
spec:
selector:
app: api
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Types:
| Type | Access | Use |
|---|---|---|
| ClusterIP | internal | default; app → app |
| NodePort | port on each node | lab, direct access |
| LoadBalancer | external IP | cloud with LB |
| ExternalName | CNAME | point to external service |
Headless (clusterIP: None) |
DNS per pod | StatefulSet |
Check if the Service found the pods:
kubectl -n portal get endpoints api
kubectl -n portal get endpointslices
If ENDPOINTS is empty, the selector didn't match any pod or the pods are not Ready. This is the #1 Service mistake.
DNS
CoreDNS resolves names inside the cluster:
api.portal.svc.cluster.local
Within the same namespace, api already resolves. Between namespaces, use api.portal or the full FQDN.
kubectl -n portal run dns --image=busybox:1.36 --rm -it --restart=Never -- \
nslookup api.portal
Beware of ndots and search domains: partial names can be tried with several suffixes before resolving. For latency-sensitive applications, use the FQDN.
NodePort and LoadBalancer
NodePort opens a port (30000–32767) on all nodes:
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
nodePort: 30080
It's useful for labs, but bad for production: it exposes ports, doesn't do TLS, and depends on the node IP. In the cloud, LoadBalancer provisions an LB; on bare metal, you need MetalLB or an equivalent.
Ingress: the HTTP entry point
Ingress is an L7 rule: host + path → Service.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: portal
namespace: portal
spec:
ingressClassName: nginx
rules:
- host: portal.exemplo.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: frontend
port:
number: 80
- path: /api
pathType: Prefix
backend:
service:
name: api
port:
number: 80
Requirements:
- An Ingress Controller installed (ingress-nginx, Traefik, etc.).
- Correct
ingressClassName. - Host DNS pointing to the controller.
- Service with healthy endpoints.
Test locally with --resolve:
curl -k --resolve portal.exemplo.com:443:127.0.0.1 https://portal.exemplo.com/
TLS with cert-manager
cert-manager issues and renews certificates. A ClusterIssuer for Let's Encrypt:
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory
email: [email protected]
privateKeySecretRef:
name: letsencrypt-prod
solvers:
- http01:
ingress:
class: nginx
In the Ingress:
metadata:
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- portal.exemplo.com
secretName: portal-tls
Monitor:
kubectl -n portal get certificate,order,challenge
kubectl -n portal describe certificate portal-tls
Use Let's Encrypt staging for tests: production has rate limits and you will hit them.
Lab
- Deploy a Deployment and a ClusterIP Service.
- Test with
port-forward. - Create an Ingress with a dummy host and test with
--resolve. - Issue a certificate (staging) and check the TLS secret.
- Force HTTP → HTTPS with an ingress-nginx annotation.
Common mistakes
| Symptom | Cause |
|---|---|
| Service without endpoints | wrong selector or pods not Ready |
| 404 on Ingress | host/path don't match or wrong class |
| 502/503 | Service without endpoints or app down |
| Certificate not issued | DNS not pointing, challenge blocked, or rate limit |
default backend - 404 |
Ingress not found in the controller |
| DNS does not resolve | CoreDNS broken or wrong namespace |
Checklist
- [ ] Service with correct selector and endpoints.
- [ ] I know the difference between ClusterIP, NodePort, and Ingress.
- [ ] Ingress with
ingressClassNameand DNS pointing. - [ ] TLS issued and renewing.
- [ ] I tested HTTP → HTTPS.
- [ ] I didn't expose NodePort unnecessarily.
Glossary
- ClusterIP: internal virtual IP of the Service.
- EndpointSlice: list of ready pods behind the Service.
- Ingress: L7 entry rule.
- Ingress Controller: implementation that applies the Ingress.
- ACME: Let's Encrypt protocol.
- ClusterIssuer: cluster-wide certificate issuer.
Next
Now that the application is accessible, let's move to the most useful chapter of the course: what to do when the pod doesn't start.
Next: Kubernetes Course 10 — The first “didn't come up”: diagnosing pods
Keep reading
Read also

StorCLI - Complete Cheat Sheet
StorCLI is the official and modern tool for managing Broadcom/LSI RAID controllers. This guide covers essential commands, syntax and use cases.
12 min de leitura
TutoriaisBusiness Services in Nyverra Portal: Translating IT into Business
The business doesn't feel a server go down — it feels email stop. The Business Services (Service Mapping) module of Nyverra ITSM Portal connects services like Email, ERP or PACS to CMDB assets, revealing the real impact of each failure.
5 min de leitura
SegurançaRPO vs RTO: How to Define Before Buying Backup (and Why Most Companies Get It Wrong)
Most companies buy backup asking the wrong question: "how much does it cost?". The right question is: how much data can I lose (RPO) and how long can I be down (RTO). Discover how to define these numbers per system and avoid purchasing protection based on price, not on real need.
9 min de leitura
Comments
No comments yet
Be the first to share your thoughts on this article.

Leave a comment