Preguntas de entrevista de Kubernetes — 40 con kubectl y YAML
Si estás preparando una entrevista para un rol de DevOps, SRE o cloud engineer, Kubernetes es el tema que no podés esquivar. No importa si la empresa corre en AWS EKS, GKE o clusters on-prem: esperan que sepas qué pasa cuando un Pod crashea, cómo escala un Deployment y por qué un Service de tipo ClusterIP no es lo mismo que un NodePort.
Esta guía tiene 40 preguntas reales de entrevista, organizadas por área, con respuestas directas y ejemplos en YAML y kubectl. Sin relleno teórico — cada respuesta te explica qué está evaluando el entrevistador y qué respuesta te diferencia del resto.
Objetos core: Pod, Deployment, ReplicaSet, StatefulSet, DaemonSet
1. ¿Cuál es la diferencia entre un Pod y un Deployment?
Respuesta: Un Pod es la unidad mínima de ejecución en Kubernetes: uno o más contenedores que comparten red y almacenamiento. Un Deployment es un objeto de nivel superior que gestiona un conjunto de Pods con rolling updates, rollbacks y autorecovery.
Si creás un Pod directamente y ese Pod muere, no vuelve. Si lo hacés con un Deployment, el ReplicaSet que crea el Deployment levanta uno nuevo automáticamente.
apiVersion: apps/v1
kind: Deployment
metadata:
name: api-backend
spec:
replicas: 3
selector:
matchLabels:
app: api-backend
template:
metadata:
labels:
app: api-backend
spec:
containers:
- name: api
image: myregistry/api:1.4.2
ports:
- containerPort: 8080Qué evalúa el entrevistador: Que entiendas que los Pods por sí solos no tienen resiliencia. El 90% de los objetos workload que vas a usar en producción son Deployments, no Pods crudos.
2. ¿Qué hace el ReplicaSet y cuándo lo usás directamente?
Respuesta: El ReplicaSet garantiza que cierta cantidad de réplicas de un Pod estén corriendo en todo momento. En la práctica casi nunca lo creás directamente: lo crea y gestiona el Deployment por vos.
La única razón para tocar un ReplicaSet directamente es cuando necesitás hacer un rollback manual examinando el historial:
kubectl rollout history deployment/api-backend
kubectl rollout undo deployment/api-backend --to-revision=2Qué evalúa el entrevistador: Que sepas la jerarquía Deployment → ReplicaSet → Pod y que no confundas gestión de réplicas con gestión de versiones.
3. ¿Cuándo usás un StatefulSet en lugar de un Deployment?
Respuesta: Cuando necesitás identidad estable por Pod: nombre predecible (pod-0, pod-1), almacenamiento persistente individual y orden de arranque/apagado garantizado. Casos típicos: bases de datos (Postgres, MySQL), sistemas de mensajería (Kafka), caches distribuidos (Redis Cluster).
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: postgres
spec:
serviceName: "postgres"
replicas: 3
selector:
matchLabels:
app: postgres
template:
metadata:
labels:
app: postgres
spec:
containers:
- name: postgres
image: postgres:16
volumeMounts:
- name: data
mountPath: /var/lib/postgresql/data
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: ["ReadWriteOnce"]
resources:
requests:
storage: 10GiLa diferencia clave con Deployment: cada Pod del StatefulSet tiene su propio PVC creado automáticamente por volumeClaimTemplates. Si el Pod-0 muere, el nuevo Pod-0 se conecta al mismo volumen.
Qué evalúa el entrevistador: Que entiendas por qué no podés correr una base de datos stateful con un Deployment simple, y que sepas el tradeoff de complejidad operacional que implica un StatefulSet.
4. ¿Para qué sirve un DaemonSet?
Respuesta: Para garantizar que exactamente un Pod corre en cada nodo (o en un subconjunto de nodos definido por nodeSelector). Casos de uso: agentes de logging (Fluentd, Filebeat), agentes de monitoreo (node-exporter de Prometheus), proxies de red (Cilium, Calico).
apiVersion: apps/v1
kind: DaemonSet
metadata:
name: node-exporter
namespace: monitoring
spec:
selector:
matchLabels:
app: node-exporter
template:
metadata:
labels:
app: node-exporter
spec:
hostNetwork: true
hostPID: true
containers:
- name: node-exporter
image: prom/node-exporter:v1.8.1
ports:
- containerPort: 9100
hostPort: 9100Si agregás un nodo al cluster, el DaemonSet le levanta el Pod automáticamente. No necesitás escalar nada manualmente.
Qué evalúa el entrevistador: Que diferencies workloads "uno por nodo" de workloads "N réplicas distribuidas". También pueden preguntarte cómo excluís nodos del DaemonSet usando tolerations + taints.
5. ¿Cuál es el ciclo de vida de un Pod y qué significan los estados `Pending`, `Running`, `CrashLoopBackOff`?
Respuesta:
- Pending: El Pod fue aceptado por el API server pero el scheduler todavía no lo asignó a un nodo (falta de recursos, taints sin toleration, nodeSelector que no matchea).
- Running: El Pod está asignado a un nodo y al menos un contenedor está corriendo.
- CrashLoopBackOff: El contenedor arranca, falla (exit code != 0) y Kubernetes lo reinicia con backoff exponencial (10s, 20s, 40s... hasta 5 min). No es un estado oficial del API, es una combinación de
Waiting+ restart count alto. - Completed: El contenedor terminó exitosamente (exit 0). Típico en Jobs.
- OOMKilled: El proceso del contenedor consumió más memoria que el límite configurado y el kernel lo mató.
# Ver el estado y los eventos de un Pod en problemas
kubectl describe pod mi-pod -n produccion
# Ver los logs del contenedor anterior (antes del crash)
kubectl logs mi-pod --previous -c nombre-contenedorQué evalúa el entrevistador: Troubleshooting práctico. Quieren saber si sabés dónde mirar cuando algo falla sin paniquear.
6. ¿Qué son los `liveness` y `readiness` probes y cuál es la diferencia?
Respuesta:
- Readiness probe: Determina si el Pod está listo para recibir tráfico. Si falla, el Pod se saca del endpoint del Service pero no se reinicia.
- Liveness probe: Determina si el contenedor sigue vivo. Si falla, Kubernetes mata y reinicia el contenedor.
livenessProbe:
httpGet:
path: /healthz
port: 8080
initialDelaySeconds: 15
periodSeconds: 10
failureThreshold: 3
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 2Error común: Configurar el liveness con initialDelaySeconds muy corto. Si la app tarda 30 segundos en arrancar y el probe empieza a los 5, Kubernetes reinicia el contenedor en un loop infinito antes de que pueda levantar.
Qué evalúa el entrevistador: Diseño para producción. Que no confundas "vivo" con "listo" — son conceptos distintos con consecuencias distintas.
7. ¿Cómo funciona el rolling update de un Deployment y cómo lo controlás?
Respuesta: El Deployment reemplaza los Pods viejos por nuevos de forma gradual, controlada por dos parámetros:
maxUnavailable: cuántos Pods pueden estar no disponibles durante el update (default: 25%)maxSurge: cuántos Pods extra por encima delreplicasse pueden crear durante el update (default: 25%)
spec:
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 1
maxSurge: 1Para ver el estado del rollout:
kubectl rollout status deployment/api-backend
# Watching rollout status...
# deployment "api-backend" successfully rolled out
kubectl rollout pause deployment/api-backend # pausar a mitad
kubectl rollout resume deployment/api-backend # continuar
kubectl rollout undo deployment/api-backend # rollback al revision anteriorQué evalúa el entrevistador: Que sepas cómo hacer deploys sin downtime y cómo revertir cuando algo sale mal.
Services e Ingress
8. ¿Cuáles son los tipos de Service en Kubernetes y cuándo usás cada uno?
Respuesta:
- ClusterIP (default): expone el Service en una IP interna del cluster. Solo accesible desde dentro del cluster. Ideal para comunicación entre microservicios.
- NodePort: expone el Service en un puerto estático de cada nodo (rango 30000-32767). Accesible desde fuera del cluster via
. Útil para testing, no para producción.: - LoadBalancer: crea un load balancer externo en el cloud provider (AWS NLB, GCP LB). El camino estándar para exponer servicios en producción en la nube.
- ExternalName: mapea el Service a un DNS externo (
CNAME). Útil para integrar servicios externos al cluster como si fueran internos.
apiVersion: v1
kind: Service
metadata:
name: api-backend-svc
spec:
type: ClusterIP
selector:
app: api-backend
ports:
- protocol: TCP
port: 80
targetPort: 8080Qué evalúa el entrevistador: Que entiendas el modelo de red de Kubernetes y no propongas un NodePort para producción sin justificación.
9. ¿Qué es un Ingress y cómo difiere de un Service LoadBalancer?
Respuesta: Un Ingress es un objeto que define reglas de routing HTTP/HTTPS a nivel de capa 7 (host-based routing, path-based routing, TLS termination). Para funcionar, necesita un Ingress Controller corriendo en el cluster (nginx-ingress, Traefik, AWS ALB Ingress Controller, etc.).
Un Service de tipo LoadBalancer expone un solo servicio en capa 4 (TCP/UDP) con una IP pública dedicada — en AWS significa un NLB por service, lo que puede volverse costoso.
Con Ingress, un solo LoadBalancer puede rutear a múltiples servicios según el host o el path:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: app-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
ingressClassName: nginx
tls:
- hosts:
- api.miapp.com
secretName: tls-miapp
rules:
- host: api.miapp.com
http:
paths:
- path: /v1
pathType: Prefix
backend:
service:
name: api-v1-svc
port:
number: 80
- path: /v2
pathType: Prefix
backend:
service:
name: api-v2-svc
port:
number: 80Qué evalúa el entrevistador: Arquitectura de red. Que sepás cuándo usar Ingress (múltiples apps HTTP detrás de un solo LB) vs LoadBalancer directo (servicio TCP de alto throughput, WebSockets con requisitos especiales).
10. ¿Cómo funciona el DNS interno de Kubernetes?
Respuesta: Kubernetes corre CoreDNS (antes kube-dns) como servicio de DNS interno. Cada Service recibe un DNS record con el formato:
<nombre-service>.<namespace>.svc.cluster.localDesde un Pod en el mismo namespace podés resolver simplemente con el nombre del Service. Desde otro namespace necesitás el FQDN:
# Desde el mismo namespace:
curl http://api-backend-svc/health
# Desde otro namespace:
curl http://api-backend-svc.produccion.svc.cluster.local/healthLos Pods de un StatefulSet también reciben DNS predecibles:
<pod-name>.<headless-service>.<namespace>.svc.cluster.localQué evalúa el entrevistador: Que no pongas IPs hardcodeadas en tus configs. Si ves una IP de ClusterIP en un ConfigMap en código de producción, es una red flag.
11. ¿Qué es un headless Service?
Respuesta: Un Service con clusterIP: None. En lugar de asignar una IP virtual y balancear, el DNS devuelve directamente los IPs de los Pods individuales. Esencial para StatefulSets: permite que cada Pod sea direccionable directamente por su nombre DNS (postgres-0.postgres.default.svc.cluster.local).
apiVersion: v1
kind: Service
metadata:
name: postgres
spec:
clusterIP: None
selector:
app: postgres
ports:
- port: 5432Qué evalúa el entrevistador: Comprensión profunda del modelo de red. Si vas a roles de platform engineering o SRE, este tipo de preguntas son habituales.
ConfigMaps y Secrets
12. ¿Cuál es la diferencia entre ConfigMap y Secret?
Respuesta: Ambos almacenan configuración, pero Secret almacena datos sensibles (contraseñas, tokens, certificados) codificados en base64. La codificación no es cifrado — cualquiera con acceso al Secret puede decodificarlo con base64 -d.
La diferencia real de seguridad la dan:
- RBAC restringido sobre Secrets (no todo service account debería poder leer todos los Secrets)
- Encryption at rest en el etcd (configuración del API server con
EncryptionConfiguration) - Herramientas externas como Vault o AWS Secrets Manager con el External Secrets Operator
# ConfigMap para config no sensible
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
DB_HOST: "postgres.produccion.svc.cluster.local"
LOG_LEVEL: "info"
MAX_CONNECTIONS: "100"# Secret para datos sensibles
apiVersion: v1
kind: Secret
metadata:
name: db-credentials
type: Opaque
stringData:
DB_PASSWORD: "mi-password-seguro" # stringData lo codifica automáticamente
DB_USER: "app_user"Qué evalúa el entrevistador: Madurez en seguridad. Espera que menciones que base64 no es seguridad y que hables de encryption at rest o soluciones externas.
13. ¿Cómo montás un ConfigMap como variables de entorno vs como archivo?
Respuesta:
Como variables de entorno individuales:
env:
- name: LOG_LEVEL
valueFrom:
configMapKeyRef:
name: app-config
key: LOG_LEVELInyectando todas las claves del ConfigMap como env vars:
envFrom:
- configMapRef:
name: app-configComo volumen (archivo en el filesystem del contenedor):
volumes:
- name: config-vol
configMap:
name: app-config
containers:
- name: app
volumeMounts:
- name: config-vol
mountPath: /etc/configCon la versión de volumen, cada clave del ConfigMap se convierte en un archivo dentro de /etc/config/. Si actualizás el ConfigMap, el archivo se actualiza automáticamente (con un delay de hasta 2 minutos). Las variables de entorno no se actualizan en caliente — requieren reinicio del Pod.
Qué evalúa el entrevistador: Que sepás el tradeoff de hot-reload: volumen sí, env vars no.
14. ¿Cómo evitás que un Secret se commitee en git por error?
Respuesta: Nunca deberías tener el YAML del Secret en git con datos reales. Las alternativas:
- 1Sealed Secrets (Bitnami): cifrás el Secret con una clave pública del cluster, el resultado encriptado sí puede estar en git.
- 2External Secrets Operator: el objeto en git es una referencia a AWS Secrets Manager / GCP Secret Manager / Vault. El operador trae el valor real al cluster.
- 3Helm + valores cifrados con SOPS: los valores sensibles en el values file están cifrados con KMS.
# ExternalSecret — lo que sí va a git
apiVersion: external-secrets.io/v1beta1
kind: ExternalSecret
metadata:
name: db-credentials
spec:
refreshInterval: 1h
secretStoreRef:
name: aws-secrets-manager
kind: ClusterSecretStore
target:
name: db-credentials
data:
- secretKey: DB_PASSWORD
remoteRef:
key: produccion/db
property: passwordQué evalúa el entrevistador: Prácticas de GitOps seguro. Esto separa a los candidatos junior de los que trabajaron en equipos con procesos reales.
RBAC y seguridad
15. ¿Cómo funciona RBAC en Kubernetes?
Respuesta: RBAC (Role-Based Access Control) controla qué acciones puede realizar qué sujeto sobre qué recursos. Los conceptos clave:
- Role / ClusterRole: define permisos (qué verbos sobre qué recursos). Role es namespaced, ClusterRole es cluster-wide.
- RoleBinding / ClusterRoleBinding: asocia un Role a un sujeto (User, Group, ServiceAccount).
# Role: solo puede leer Pods en el namespace "produccion"
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: produccion
name: pod-reader
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
# RoleBinding: le da ese Role al ServiceAccount "monitor-sa"
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: read-pods
namespace: produccion
subjects:
- kind: ServiceAccount
name: monitor-sa
namespace: produccion
roleRef:
kind: Role
name: pod-reader
apiGroup: rbac.authorization.k8s.ioPara verificar permisos:
kubectl auth can-i list pods --namespace=produccion --as=system:serviceaccount:produccion:monitor-saQué evalúa el entrevistador: Que no des cluster-admin a todo el mundo "para que funcione". El principio de mínimo privilegio es no negociable en producción.
16. ¿Qué es un ServiceAccount y por qué importa?
Respuesta: Un ServiceAccount es una identidad para los Pods (no para usuarios humanos). Por default, cada Pod usa el ServiceAccount default del namespace, que en instalaciones sin RBAC restrictivo puede tener más acceso del necesario.
La buena práctica es crear un ServiceAccount específico por workload con solo los permisos que necesita:
apiVersion: v1
kind: ServiceAccount
metadata:
name: api-backend-sa
namespace: produccion
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::123456789:role/api-backend-role # IRSA en EKSEn EKS esto se llama IRSA (IAM Roles for Service Accounts): el Pod asume un rol IAM de AWS sin necesidad de credenciales hardcodeadas.
Qué evalúa el entrevistador: Gestión de identidad y credenciales en producción. Conocimiento de IRSA es muy valorado en entrevistas para roles en AWS.
17. ¿Qué es un NetworkPolicy y cómo lo configurás?
Respuesta: Un NetworkPolicy define reglas de firewall a nivel de Pod. Por default, todos los Pods en un cluster pueden comunicarse entre sí (todo permitido). NetworkPolicy cambia eso.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-netpol
namespace: produccion
spec:
podSelector:
matchLabels:
app: api-backend
policyTypes:
- Ingress
- Egress
ingress:
- from:
- podSelector:
matchLabels:
app: frontend
ports:
- protocol: TCP
port: 8080
egress:
- to:
- podSelector:
matchLabels:
app: postgres
ports:
- protocol: TCP
port: 5432Este policy dice: el Pod api-backend solo acepta tráfico entrante del Pod frontend en el puerto 8080, y solo puede salir hacia postgres en el 5432.
Importante: NetworkPolicy solo funciona si el CNI del cluster lo soporta (Calico, Cilium, Weave). Flannel, por ejemplo, no implementa NetworkPolicy.
Qué evalúa el entrevistador: Segmentación de red. Un candidato senior menciona espontáneamente la dependencia del CNI.
18. ¿Qué es un PodSecurityContext y qué configuraciones críticas incluye?
Respuesta: Define el contexto de seguridad a nivel de Pod y contenedor: usuario/grupo, capabilities, filesystem read-only, etc.
spec:
securityContext:
runAsNonRoot: true
runAsUser: 1000
runAsGroup: 3000
fsGroup: 2000
containers:
- name: app
image: myapp:1.0
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICEConfiguraciones críticas:
runAsNonRoot: true— no correr como root dentro del contenedorreadOnlyRootFilesystem: true— si el app no necesita escribir, no le des esa capacidadallowPrivilegeEscalation: false— impide que el proceso hijo obtenga más privilegios que el padrecapabilities: drop: ALL— elimina todas las Linux capabilities y agrega solo las necesarias
Qué evalúa el entrevistador: Defense in depth. En una entrevista de SRE/platform engineer, esperan que menciones Pod Security Admission (PSA) como el mecanismo de enforcement desde Kubernetes 1.25 (reemplazó PSP).
Horizontal Pod Autoscaler
19. ¿Cómo funciona el HPA y qué métricas puede usar?
Respuesta: El HPA (Horizontal Pod Autoscaler) ajusta automáticamente el número de réplicas de un Deployment, ReplicaSet o StatefulSet basándose en métricas observadas.
Métricas disponibles:
- Resource metrics (CPU, memoria) — vienen del metrics-server
- Custom metrics — de Prometheus via prometheus-adapter (req/s, queue depth, etc.)
- External metrics — de sistemas externos (mensajes en SQS, latencia de RDS, etc.)
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: api-hpa
spec:
scaleTargetRef:
apiVersion: apps/v1
kind: Deployment
name: api-backend
minReplicas: 2
maxReplicas: 20
metrics:
- type: Resource
resource:
name: cpu
target:
type: Utilization
averageUtilization: 70
- type: Resource
resource:
name: memory
target:
type: Utilization
averageUtilization: 80Requisito indispensable: Los Pods deben tener resources.requests definidos para que el HPA pueda calcular el porcentaje de uso. Si no tenés requests, el HPA no puede escalar por CPU/memoria.
kubectl get hpa api-hpa
# NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS
# api-hpa Deployment/api-back 45%/70% 2 20 3Qué evalúa el entrevistador: Que sepas que HPA necesita metrics-server, que los requests son obligatorios, y que hables del cooldown period (default 5 min para scale-down) para evitar flapping.
20. ¿Cuál es la diferencia entre HPA y VPA?
Respuesta:
- HPA (Horizontal): agrega o quita réplicas (escala horizontalmente)
- VPA (Vertical Pod Autoscaler): ajusta los
requestsylimitsde CPU/memoria de los Pods existentes (escala verticalmente)
El VPA puede reiniciar Pods para aplicar los nuevos valores de recursos (modo Auto), lo que lo hace riesgoso en workloads sin tolerancia a reinicios. El modo Off solo recomienda valores sin aplicarlos.
Regla general: No usar HPA y VPA juntos en la misma dimensión (CPU) — pueden entrar en conflicto. Podés usar HPA en CPU y VPA en modo Off para que recomiende el tamaño correcto de los requests.
Qué evalúa el entrevistador: Conocimiento del ecosistema más allá del HPA básico.
PersistentVolumes
21. ¿Cuál es la diferencia entre PersistentVolume, PersistentVolumeClaim y StorageClass?
Respuesta:
- PersistentVolume (PV): recurso de almacenamiento provisionado en el cluster (puede ser EBS, NFS, un disco local, etc.). Es cluster-wide.
- PersistentVolumeClaim (PVC): la solicitud de almacenamiento que hace un Pod. Define cuánto espacio quiere y qué access mode necesita.
- StorageClass: define el "tipo" de almacenamiento (gp3, io1, standard) y su provisioner. Con dynamic provisioning, la StorageClass crea el PV automáticamente cuando se crea un PVC.
# PVC — lo que define el desarrollador
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: postgres-data
spec:
accessModes:
- ReadWriteOnce
storageClassName: gp3
resources:
requests:
storage: 50GiEl PV se crea automáticamente por el provisioner de AWS EBS (o el que corresponda). No necesitás crear el PV manualmente con dynamic provisioning.
Access modes:
ReadWriteOnce (RWO): lectura/escritura por un solo nodoReadOnlyMany (ROX): lectura por múltiples nodosReadWriteMany (RWX): lectura/escritura por múltiples nodos (requiere NFS, EFS, CephFS — EBS no lo soporta)
Qué evalúa el entrevistador: Que entiendas el modelo de abstracción y la diferencia entre RWO y RWX, que es donde la gente se confunde al diseñar storage compartido.
22. ¿Qué pasa con el PV cuando se borra el PVC?
Respuesta: Depende de la reclaimPolicy del PV o la StorageClass:
- Delete (default en dynamic provisioning): se borra el PV y el volumen subyacente (el EBS, el disco). Peligroso si lo hacés por error.
- Retain: el PV queda en estado
Releasedpero no se borra. Podés recuperar los datos, pero tenés que limpiar manualmente y rebindear el PV si lo querés reutilizar. - Recycle (deprecated): formateaba el volumen y lo ponía disponible de nuevo.
# Ver la reclaim policy de los PVs
kubectl get pv -o custom-columns='NAME:.metadata.name,POLICY:.spec.persistentVolumeReclaimPolicy,STATUS:.status.phase'Qué evalúa el entrevistador: Gestión de datos en producción. La respuesta correcta incluye que en producción deberías usar Retain para datos críticos y tener backups automáticos con Velero o equivalente.
Helm Charts
23. ¿Qué es Helm y cuándo lo usás?
Respuesta: Helm es el package manager de Kubernetes. Un chart es un conjunto de templates YAML parametrizados. En lugar de mantener 20 archivos YAML con pequeñas diferencias entre staging y producción, tenés un chart con un values.yaml por ambiente.
mi-app/
├── Chart.yaml
├── values.yaml
├── values-staging.yaml
├── values-production.yaml
└── templates/
├── deployment.yaml
├── service.yaml
├── ingress.yaml
└── _helpers.tpl# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mi-app.fullname" . }}
labels:
{{- include "mi-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
template:
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
resources:
{{- toYaml .Values.resources | nindent 12 }}Comandos básicos:
helm install mi-app ./mi-app -f values-production.yaml -n produccion
helm upgrade mi-app ./mi-app -f values-production.yaml -n produccion
helm rollback mi-app 1 -n produccion
helm list -n produccionQué evalúa el entrevistador: Que no respondas "copio y pego el YAML" para cada ambiente. Helm o Kustomize son los dos enfoques más comunes — deberías saber al menos uno bien.
24. ¿Cuál es la diferencia entre Helm y Kustomize?
Respuesta:
- Helm: templating engine con lógica (condicionales, loops, funciones). Los valores se pasan como parámetros. Tiene un registry de charts públicos. Gestiona el ciclo de vida del release (install/upgrade/rollback) con estado guardado en Secrets del cluster.
- Kustomize: overlays sobre YAML base. No usa templating — usa patches y transformaciones. Viene integrado en kubectl (
kubectl apply -k). Sin estado — no sabe qué versión está deployada.
Cuándo usar cada uno:
- Helm: cuando distribuís tu app para que otros la instalen (chart público), o cuando tenés lógica compleja de configuración.
- Kustomize: cuando gestionás tus propios manifests con variaciones por ambiente y querés algo más simple y auditable.
En la práctica muchos equipos usan Helm para dependencias externas (nginx-ingress, cert-manager) y Kustomize para sus propias apps.
Qué evalúa el entrevistador: Que hayas trabajado con ambos y puedas justificar la elección según el contexto.
Troubleshooting con kubectl
25. Un Pod está en `CrashLoopBackOff`. ¿Qué pasos seguís?
Respuesta: Pasos en orden:
# 1. Ver el estado y los últimos eventos
kubectl describe pod <nombre-pod> -n <namespace>
# Buscar en la sección "Events" mensajes como OOMKilled, ImagePullBackOff, etc.
# 2. Ver los logs del contenedor que crasheó
kubectl logs <nombre-pod> -n <namespace>
# 3. Si el contenedor se reinició y no podés ver los logs del run actual:
kubectl logs <nombre-pod> -n <namespace> --previous
# 4. Si hay múltiples contenedores en el Pod:
kubectl logs <nombre-pod> -n <namespace> -c <nombre-contenedor>
# 5. Si el contenedor crashea tan rápido que no podés hacer nada:
# Cambiar el comando del contenedor temporalmente para que no falle:
kubectl debug pod/<nombre-pod> -n <namespace> --copy-to=debug-pod --image=busybox -- sleep 3600Causas comunes:
- OOMKilled: memory limit demasiado bajo, hay que ajustar o hay un leak
- Error de configuración: variable de entorno mal seteada, Secret inexistente
- Falla de conexión a DB: la DB no está disponible en el arranque (falta init container o retry logic)
- Error en el entrypoint: el comando del contenedor falla inmediatamente
Qué evalúa el entrevistador: Método sistemático. No quieren que adivines — quieren ver que sabés exactamente dónde buscar.
26. Un Pod está en `Pending` hace 10 minutos. ¿Qué puede estar pasando?
Respuesta:
kubectl describe pod <nombre-pod> -n <namespace>
# Mirar la sección "Events" al finalCausas más comunes:
- 1Recursos insuficientes: el Pod pide más CPU/memoria de lo que hay disponible en cualquier nodo.
kubectl describe nodes | grep -A 5 "Allocated resources"- 2Taint sin toleration: el nodo tiene un taint que el Pod no tolera.
kubectl describe node <nombre-nodo> | grep Taints- 3NodeSelector o Affinity que no matchea: el Pod pide correr en un nodo con un label que no existe.
- 4PVC no bound: el Pod tiene un volume claim que no pudo bindear a un PV.
kubectl get pvc -n <namespace>- 5Límite de Pods por nodo alcanzado (default 110 en la mayoría de las distros).
Qué evalúa el entrevistador: Capacidad de diagnóstico metódico. La respuesta completa incluye revisar el describe pod primero y luego describir el nodo si los eventos del Pod no son suficientes.
27. ¿Cómo ejecutás un comando dentro de un Pod corriendo?
Respuesta:
# Shell interactivo
kubectl exec -it <nombre-pod> -n <namespace> -- /bin/bash
# Si no tiene bash:
kubectl exec -it <nombre-pod> -n <namespace> -- /bin/sh
# En un Pod con múltiples contenedores:
kubectl exec -it <nombre-pod> -n <namespace> -c <nombre-contenedor> -- /bin/bash
# Comando one-shot sin shell interactivo:
kubectl exec <nombre-pod> -n <namespace> -- env | grep DB_
# Verificar conectividad de red desde dentro del Pod:
kubectl exec -it <nombre-pod> -n <namespace> -- curl -v http://postgres:5432Qué evalúa el entrevistador: Conocimiento básico de operaciones. También pueden preguntarte qué hacer si el contenedor no tiene herramientas de networking (curl, nc) — la respuesta es usar kubectl debug con una imagen efímera:
kubectl debug -it <nombre-pod> --image=nicolaka/netshoot --target=<nombre-contenedor>28. ¿Cómo hacés port-forward para acceder a un servicio en el cluster desde tu máquina local?
Respuesta:
# Port-forward a un Pod directamente:
kubectl port-forward pod/<nombre-pod> 8080:8080 -n produccion
# Port-forward a un Service (recomendado — usa el load balancing del Service):
kubectl port-forward svc/api-backend-svc 8080:80 -n produccion
# Port-forward a un Deployment:
kubectl port-forward deployment/api-backend 8080:8080 -n produccionAhora podés acceder en http://localhost:8080. Esto es para debugging/desarrollo — no para producción.
Qué evalúa el entrevistador: Herramientas de desarrollo diario. Simple, pero quieren confirmar que sabés trabajar sin necesitar acceso externo al cluster.
29. ¿Cómo ves los logs de múltiples Pods al mismo tiempo?
Respuesta: kubectl nativo solo loguea un Pod a la vez. Para múltiples Pods en paralelo:
# kubectl nativo — logs de todos los Pods con el label app=api-backend:
kubectl logs -l app=api-backend -n produccion --follow
# stern — herramienta open source para multi-pod logs con colores:
stern api-backend -n produccion
# Con filtro de contenedor:
stern api-backend -n produccion -c app --since 1hEn producción deberías tener un stack de logging centralizado (ELK, Loki+Grafana, Datadog) para que no dependas de kubectl logs — los logs se pierden cuando el Pod muere o rota.
Qué evalúa el entrevistador: Que sepás que kubectl logs no escala y que hables de logging centralizado como práctica estándar.
30. ¿Cómo filtrás Pods por estado o por label?
Respuesta:
# Listar Pods con sus estados:
kubectl get pods -n produccion -o wide
# Filtrar por label:
kubectl get pods -l app=api-backend,env=produccion -n produccion
# Filtrar Pods que no están en Running:
kubectl get pods -n produccion --field-selector=status.phase!=Running
# Ver todos los Pods del cluster en todos los namespaces:
kubectl get pods --all-namespaces
# Ordenar por restart count (útil para encontrar Pods inestables):
kubectl get pods -n produccion --sort-by='.status.containerStatuses[0].restartCount'Qué evalúa el entrevistador: Fluencia con kubectl. Los entrevistadores de operaciones esperan que estas líneas te salgan de memoria.
Patrones multi-container
31. ¿Qué es el patrón sidecar y cuándo lo usás?
Respuesta: Un sidecar es un contenedor secundario que corre junto al contenedor principal en el mismo Pod, extendiendo su funcionalidad sin modificarlo.
Casos de uso comunes:
- Proxy de service mesh: Envoy/Istio sidecar que intercepta el tráfico de red
- Log shipper: Fluentd que lee los logs del filesystem compartido y los manda a Elasticsearch
- Secret rotation: un contenedor que renueva certificados y los escribe en un volumen compartido
spec:
containers:
- name: app
image: myapp:1.0
volumeMounts:
- name: logs
mountPath: /var/log/app
- name: log-shipper
image: fluent/fluentd:v1.16
volumeMounts:
- name: logs
mountPath: /var/log/app
readOnly: true
- name: fluentd-config
mountPath: /fluentd/etc
volumes:
- name: logs
emptyDir: {}
- name: fluentd-config
configMap:
name: fluentd-configLos contenedores comparten la red (localhost) y pueden compartir volúmenes. El sidecar y el main container se schedulean siempre juntos en el mismo nodo.
Qué evalúa el entrevistador: Diseño de arquitectura de microservicios. Los sidecars de service mesh son un tema muy frecuente en roles que trabajan con Istio o Linkerd.
32. ¿Qué son los init containers y para qué sirven?
Respuesta: Los init containers corren antes que los contenedores principales del Pod, en orden secuencial. Si un init container falla, el Pod no arranca. Si pasan todos, entonces sí arrancan los contenedores principales.
Casos de uso:
- Esperar a que una base de datos esté disponible antes de arrancar la app
- Clonar repositorios o descargar assets
- Aplicar migraciones de DB (aunque muchos prefieren un Job separado)
- Configurar permisos de volúmenes
spec:
initContainers:
- name: wait-for-postgres
image: busybox:1.36
command: ['sh', '-c',
'until nc -z postgres.produccion.svc.cluster.local 5432; do
echo waiting for postgres; sleep 2;
done']
- name: run-migrations
image: myapp-migrations:1.0
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: DATABASE_URL
containers:
- name: app
image: myapp:1.0Los init containers no se reinician si fallan después de haberse completado — el Pod vuelve a correrlos desde cero si es reiniciado.
Qué evalúa el entrevistador: Manejo de dependencias entre servicios al arrancar. El antipatrón es tener retry logic en la app principal con timeouts largos — los init containers son más limpios.
Arquitectura del cluster
33. ¿Cuáles son los componentes del control plane de Kubernetes?
Respuesta:
- kube-apiserver: el punto de entrada de todas las operaciones. Todo (kubectl, el scheduler, los controllers) habla con el API server. Es el único componente que escribe directamente en etcd.
- etcd: almacén clave-valor distribuido donde se persiste todo el estado del cluster. Si perdés etcd sin backup, perdés el cluster.
- kube-scheduler: decide en qué nodo corre cada Pod nuevo, basándose en recursos disponibles, taints/tolerations, affinity rules.
- kube-controller-manager: corre los controllers (Deployment controller, ReplicaSet controller, Node controller, etc.). Un controller es un loop que observa el estado actual y lo reconcilia con el estado deseado.
- cloud-controller-manager: interactúa con el API del cloud provider para crear Load Balancers, volúmenes, etc.
# En un cluster administrado (EKS, GKE, AKS) no ves el control plane
# En un cluster self-managed, los componentes corren como Pods en el namespace kube-system:
kubectl get pods -n kube-systemQué evalúa el entrevistador: Comprensión de la arquitectura completa. Una respuesta de nivel senior menciona que el API server es stateless (toda la data está en etcd) y por eso podés correr múltiples réplicas del API server para HA.
34. ¿Qué componentes corren en cada nodo worker?
Respuesta:
- kubelet: el agente del nodo. Recibe las especificaciones de Pods del API server y se asegura de que los contenedores estén corriendo. También reporta el estado del nodo y los Pods al API server.
- kube-proxy: mantiene las reglas de red del nodo (iptables o IPVS) para implementar los Services. Cuando creás un Service, kube-proxy es quien programa las reglas que redirigen el tráfico a los Pods correctos.
- Container runtime: el proceso que realmente corre los contenedores. Kubernetes usa la CRI (Container Runtime Interface): Docker (vía cri-dockerd), containerd, CRI-O.
Qué evalúa el entrevistador: Que entiendas que "el nodo" no es solo un servidor con contenedores — tiene una capa de agente y proxy que hacen el trabajo sucio.
35. ¿Qué son los taints y tolerations?
Respuesta: Los taints le dicen a los Pods "no corras en este nodo a menos que lo toleres". Las tolerations son la respuesta del Pod: "sí, puedo tolerar ese taint".
# Agregar un taint a un nodo:
kubectl taint nodes nodo-gpu gpu=true:NoSchedule
# Ahora solo Pods con esta toleration se schedulean en ese nodo:tolerations:
- key: "gpu"
operator: "Equal"
value: "true"
effect: "NoSchedule"Efectos disponibles:
NoSchedule: nuevos Pods sin toleration no se schedulean (los existentes quedan)PreferNoSchedule: el scheduler prefiere no poner Pods ahí, pero puede si no hay alternativaNoExecute: nuevos Pods no se schedulean Y los existentes sin toleration son desalojados
Los taints también se usan internamente: cuando un nodo tiene problemas, Kubernetes le agrega taints automáticamente (node.kubernetes.io/not-ready, node.kubernetes.io/unreachable).
Qué evalúa el entrevistador: Gestión de nodos especializados (GPU, large memory, spot instances). Muy común en roles que trabajan con ML workloads o clusters de costo optimizado.
36. ¿Qué es node affinity y cómo difiere de nodeSelector?
Respuesta:
nodeSelector es la forma simple y rígida: "este Pod solo corre en nodos con este label exacto".
nodeAffinity es más expresivo: soporta operadores (In, NotIn, Exists, Gt), reglas requeridas vs preferidas, y múltiples condiciones.
affinity:
nodeAffinity:
# REQUERIDO: si no hay nodo que matchee, el Pod no se schedulea
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values:
- amd64
- key: node-type
operator: NotIn
values:
- spot
# PREFERIDO: si hay un nodo que matchee, se prefiere pero no es obligatorio
preferredDuringSchedulingIgnoredDuringExecution:
- weight: 100
preference:
matchExpressions:
- key: zone
operator: In
values:
- us-east-1aTambién existe podAffinity / podAntiAffinity para colocar Pods cerca o lejos de otros Pods (útil para alta disponibilidad: distribuir réplicas entre zonas).
Qué evalúa el entrevistador: Diseño de scheduling avanzado. Anti-affinity entre réplicas para HA es un tema que aparece mucho en entrevistas de plataforma.
37. ¿Qué son los resource requests y limits y por qué son importantes?
Respuesta:
- requests: lo que el Pod garantiza que va a necesitar. El scheduler usa esto para decidir en qué nodo colocar el Pod.
- limits: el máximo que el Pod puede consumir. Si supera el límite de CPU, se throttlea. Si supera el de memoria, se mata (OOMKilled).
resources:
requests:
cpu: "250m" # 0.25 CPU cores
memory: "256Mi"
limits:
cpu: "1000m" # 1 CPU core
memory: "512Mi"Qué pasa si no los configurás:
- Sin requests: el scheduler no sabe dónde colocar el Pod apropiadamente → over-scheduling de nodos
- Sin limits: un Pod puede consumir todos los recursos de un nodo y matar a otros Pods (noisy neighbor)
Clases de QoS que define Kubernetes automáticamente:
- Guaranteed: requests == limits. Máxima prioridad, último en ser evictado.
- Burstable: tiene requests pero limits > requests.
- BestEffort: sin requests ni limits. Primero en ser evictado bajo presión de recursos.
Qué evalúa el entrevistador: Operaciones en producción. Un candidato sin experiencia real no sabe sobre las QoS classes — es una señal de madurez operacional.
38. ¿Qué es el namespace en Kubernetes y cómo lo usás para organizar un cluster?
Respuesta: Los namespaces son una forma de dividir virtualmente un cluster en "clusters lógicos". Permiten:
- Aislar recursos entre equipos/proyectos/ambientes
- Aplicar ResourceQuotas por namespace
- Scoped RBAC (Roles en lugar de ClusterRoles)
- NetworkPolicies por namespace
# Crear namespace
kubectl create namespace produccion
# Ver todos los namespaces
kubectl get namespaces
# Trabajar en un namespace sin especificarlo siempre:
kubectl config set-context --current --namespace=produccion
# Ver recursos de todos los namespaces:
kubectl get pods --all-namespacesResourceQuota por namespace:
apiVersion: v1
kind: ResourceQuota
metadata:
name: produccion-quota
namespace: produccion
spec:
hard:
requests.cpu: "10"
requests.memory: 20Gi
limits.cpu: "20"
limits.memory: 40Gi
pods: "50"Qué evalúa el entrevistador: Diseño de clusters multi-tenant. La discusión interesante es si usar un cluster por ambiente vs namespaces — no hay respuesta única, pero deberías poder argumentar los tradeoffs.
39. ¿Qué es un Job y un CronJob en Kubernetes?
Respuesta:
- Job: crea uno o más Pods que corren hasta completarse (exit 0). Si el Pod falla, lo reinicia hasta
backoffLimitveces. - CronJob: crea Jobs en un schedule definido por una expresión cron.
apiVersion: batch/v1
kind: Job
metadata:
name: migrate-db
spec:
backoffLimit: 3
template:
spec:
restartPolicy: OnFailure
containers:
- name: migration
image: myapp-migrations:1.0
command: ["python", "manage.py", "migrate"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: DATABASE_URLapiVersion: batch/v1
kind: CronJob
metadata:
name: cleanup-job
spec:
schedule: "0 2 * * *" # Todos los días a las 2am UTC
concurrencyPolicy: Forbid # No correr si el anterior no terminó
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: cleanup
image: myapp:1.0
command: ["python", "cleanup.py"]Qué evalúa el entrevistador: restartPolicy es obligatorio en Jobs y no puede ser Always (que sería el default). Los valores válidos son OnFailure o Never. Este error de configuración es muy común.
40. ¿Cómo implementás un blue/green deployment en Kubernetes?
Respuesta: Kubernetes no tiene un objeto nativo para blue/green, pero se implementa con Services y labels:
# Blue (versión actual) corriendo:
# Deployment: api-blue con image:1.0, label version=blue
# Service apunta a version=blue
# Deployar green (versión nueva) en paralelo:
kubectl apply -f deployment-green.yaml # image:1.1, label version=green
# Esperar a que green esté healthy:
kubectl rollout status deployment/api-green
# Cambiar el Service para apuntar a green (cutover instantáneo):
kubectl patch service api-svc -p '{"spec":{"selector":{"version":"green"}}}'
# Verificar que todo funciona
# Si hay problema, rollback en segundos:
kubectl patch service api-svc -p '{"spec":{"selector":{"version":"blue"}}}'
# Una vez que estás seguro, borrar blue:
kubectl delete deployment api-blueCon Argo Rollouts o Flagger podés automatizar esto con análisis de métricas y rollback automático basado en error rate o latencia.
Qué evalúa el entrevistador: Estrategias de deployment de bajo riesgo. El candidato senior menciona espontáneamente que blue/green implica el doble de recursos durante el cutover y que Argo Rollouts existe para automatizarlo.
Errores comunes que hay que evitar en entrevistas
No confundas:
kubectl applyvskubectl create—applyhace upsert (idempotente),createfalla si ya existeClusterIPvsNodePortvsLoadBalancer— cada uno para un caso distintoDeploymentpara stateless,StatefulSetpara stateful — nunca al revés
Banderas rojas para el entrevistador:
- Decir que base64 = cifrado
- No saber qué hacer cuando un Pod está en Pending
- No mencionar
resources.requestsal hablar de HPA - Proponer un NodePort para un servicio de producción sin justificación
- No saber la diferencia entre liveness y readiness probe
Lo que te diferencia:
- Hablar del modelo de conciliación (el controller loop que reconcilia desired state vs actual state)
- Mencionar herramientas del ecosistema (Helm, Kustomize, Argo, Velero, External Secrets Operator)
- Saber cuándo NO usar Kubernetes (un monolito con un solo servicio no necesita k8s)
- Hablar de observabilidad: métricas con Prometheus, trazas con Jaeger, logs con Loki
Cómo preparar la entrevista de Kubernetes
- 1Configurá un cluster local: usa
kind(Kubernetes in Docker) ominikube. No hay sustituto para la práctica con kubectl. - 2Rompé cosas a propósito: eliminá un Pod, llenale la memoria, rompé una NetworkPolicy. Aprender a diagnosticar viene de haber visto los errores.
- 3Conocé el stack completo: en casi todos los roles de DevOps, Kubernetes es solo una pieza. También esperan Docker, IaC (Terraform), CI/CD (GitLab CI, GitHub Actions), y cloud nativo (EKS/GKE/AKS).
- 4Practicá explicaciones en voz alta: podés saber el concepto pero trabarte al explicarlo bajo presión. La práctica de verbalizar es clave.
Si querés simular una entrevista completa con feedback en tiempo real, [InterviewHack.ai](/) te arma un dossier con las preguntas más frecuentes del rol y empresa exacta a la que aplicaste, con análisis de tus respuestas.