Clase 07 — YAML en Kubernetes
Estructura básica de un manifiesto K8s
Todos los recursos de Kubernetes comparten estos campos:
apiVersion: v1 # Versión de la API
kind: Pod # Tipo de recurso
metadata: # Metadatos
name: mi-pod
namespace: default
labels:
app: mi-app
spec: # Especificación (varía por tipo)
# ...
Pod
La unidad mínima en Kubernetes.
apiVersion: v1
kind: Pod
metadata:
name: mi-pod
labels:
app: mi-app
env: development
spec:
containers:
- name: app
image: nginx:1.25-alpine
ports:
- containerPort: 80
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "250m"
memory: "256Mi"
Deployment
Gestiona réplicas y actualizaciones de Pods.
apiVersion: apps/v1
kind: Deployment
metadata:
name: mi-api
labels:
app: mi-api
spec:
replicas: 3
selector:
matchLabels:
app: mi-api
strategy:
type: RollingUpdate
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
template:
metadata:
labels:
app: mi-api
version: "2.0"
spec:
containers:
- name: api
image: mi-registry/mi-api:2.0
ports:
- containerPort: 8080
env:
- name: APP_ENV
value: "production"
- name: DB_HOST
valueFrom:
configMapKeyRef:
name: db-config
key: host
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: db-secret
key: password
resources:
requests:
cpu: "250m"
memory: "256Mi"
limits:
cpu: "500m"
memory: "512Mi"
livenessProbe:
httpGet:
path: /health
port: 8080
initialDelaySeconds: 15
periodSeconds: 20
readinessProbe:
httpGet:
path: /ready
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
Service
Expone los Pods como un servicio de red.
# ClusterIP (interno)
apiVersion: v1
kind: Service
metadata:
name: mi-api-svc
spec:
type: ClusterIP
selector:
app: mi-api
ports:
- protocol: TCP
port: 80
targetPort: 8080
---
# NodePort (acceso externo por puerto del nodo)
apiVersion: v1
kind: Service
metadata:
name: mi-api-nodeport
spec:
type: NodePort
selector:
app: mi-api
ports:
- port: 80
targetPort: 8080
nodePort: 30080
---
# LoadBalancer (cloud provider)
apiVersion: v1
kind: Service
metadata:
name: mi-api-lb
spec:
type: LoadBalancer
selector:
app: mi-api
ports:
- port: 80
targetPort: 8080
ConfigMap
Almacena configuración no sensible.
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_ENV: "production"
LOG_LEVEL: "info"
DB_HOST: "postgres-svc"
DB_PORT: "5432"
app.conf: |
[server]
host = 0.0.0.0
port = 8080
workers = 4
[database]
pool_size = 10
timeout = 30
nginx.conf: |
server {
listen 80;
location / {
proxy_pass http://mi-api-svc:80;
}
}
Usar ConfigMap en un Pod
apiVersion: v1
kind: Pod
metadata:
name: mi-app
spec:
containers:
- name: app
image: mi-app:latest
envFrom:
- configMapRef:
name: app-config
env:
- name: DATABASE_HOST
valueFrom:
configMapKeyRef:
name: app-config
key: DB_HOST
volumeMounts:
- name: config-volume
mountPath: /etc/app
volumes:
- name: config-volume
configMap:
name: app-config
items:
- key: app.conf
path: app.conf
- key: nginx.conf
path: nginx.conf
Secret
Almacena datos sensibles (codificados en base64).
apiVersion: v1
kind: Secret
metadata:
name: db-secret
type: Opaque
data:
# echo -n "valor" | base64
username: YWRtaW4= # admin
password: cDRzc3cwcmQ= # p4ssw0rd
---
# stringData: texto plano, se codifica automáticamente
apiVersion: v1
kind: Secret
metadata:
name: db-secret-v2
type: Opaque
stringData:
username: admin
password: p4ssw0rd
Ingress
Gestiona acceso HTTP/HTTPS externo.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: mi-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
ingressClassName: nginx
tls:
- hosts:
- api.ejemplo.com
secretName: api-tls
rules:
- host: api.ejemplo.com
http:
paths:
- path: /api
pathType: Prefix
backend:
service:
name: mi-api-svc
port:
number: 80
- path: /
pathType: Prefix
backend:
service:
name: frontend-svc
port:
number: 80
Múltiples documentos en un archivo
Usá --- para separar recursos en un mismo archivo.
apiVersion: v1
kind: Namespace
metadata:
name: pokemon-app
---
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
namespace: pokemon-app
data:
APP_ENV: production
API_PORT: "8080"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: pokemon-api
namespace: pokemon-app
spec:
replicas: 2
selector:
matchLabels:
app: pokemon-api
template:
metadata:
labels:
app: pokemon-api
spec:
containers:
- name: api
image: pokemon-api:latest
ports:
- containerPort: 8080
envFrom:
- configMapRef:
name: app-config
---
apiVersion: v1
kind: Service
metadata:
name: pokemon-api-svc
namespace: pokemon-app
spec:
selector:
app: pokemon-api
ports:
- port: 80
targetPort: 8080
type: ClusterIP
Comandos útiles
kubectl apply -f deployment.yaml # Aplicar manifiesto
kubectl apply -f k8s/ # Aplicar todo un directorio
kubectl apply -f deployment.yaml --dry-run=client # Validar sin aplicar
kubectl get deployment mi-api -o yaml # Ver YAML de un recurso
kubectl create deployment mi-app --image=nginx --dry-run=client -o yaml > deployment.yaml
Ejercicios
- Creá un manifiesto completo con: Namespace, ConfigMap, Secret, Deployment y Service
- Configurá un Deployment con probes (liveness y readiness) y límites de recursos
- Creá un Ingress que enrute
/apia un backend y/a un frontend