🔎 Buscar

🐧 DevOps e infraestructura — contenido

Linux a nivel administrador, systemd, servidores y Nginx, redes y firewalls, Docker, Kubernetes, CI/CD, monitoreo y cloud. Teoría, comandos y práctica.

DevOps & Infra📖 Contenido

DevOps e infraestructura — contenido

Un backend no vale nada si no sabes operarlo. Esta página te da el contenido completo de infraestructura: de la terminal al servidor de producción, pasando por systemd, Nginx, firewalls, Docker y Kubernetes. Primero a mano (vanilla), luego con herramientas — la regla de oro del DevOps serio.

Las wikis del sitio tienen detalle por tema: Comandos Linux, Bash, Nginx, Docker, Firewalls. Y las páginas de la ruta tienen los recursos: Linux, Servidores, Redes y seguridad, Infraestructura moderna, Cloud.

Linux: el sistema operativo de los servidores

Linux domina los servidores (y los contenedores son Linux). Los conceptos que debes dominar a nivel administrador:

El árbol de directorios

/              raíz
/etc/          configuración del sistema (nginx.conf, sshd_config)
/var/log/      logs (nginx/access.log, syslog, journald)
/var/www/      web roots
/home/         usuarios
/tmp/          temporales
/usr/bin/      binarios de sistema
/proc/         archivos virtuales del kernel (procesos, memoria)
/sys/          interfaz del kernel con el hardware

💡 /proc y /sys son ilusiones: leer cat /proc/meminfo o /proc/1234/status NO lee archivos de disco; el kernel genera esos “archivos” en el momento. Por eso el SO es «una fábrica de ilusiones».

Permisos y usuarios (lo viste en Fundamentos SO)

ls -la
-rw-r--r-- 1 ana dev 4096 mar 3 12:00 app.log
drwxr-xr-x 2 ana dev 4096 mar 3 12:00 proyecto

chmod 755 script.sh     # rwxr-xr-x
chmod 644 config.conf   # rw-r--r--
chown ana:dev archivo   # cambiar dueño:grupo
adduser nuevo_usuario
usermod -aG sudo nuevo_usuario   # añadir al grupo sudo

Procesos y systemd

systemd es el gestor de servicios moderno de casi todas las distros. Sustituye al viejo init.

systemctl status nginx        # ¿estado de nginx?
systemctl start/stop/restart nginx
systemctl enable nginx        # arrancar al boot
systemctl reload nginx        # recargar config sin cortar
journalctl -u nginx -f        # logs del servicio en vivo

Cada servicio es una unit en /etc/systemd/system/:

# /etc/systemd/system/miapp.service
[Unit]
Description=Mi aplicación
After=network.target postgresql.service

[Service]
User=ana
WorkingDirectory=/var/www/miapp
ExecStart=/usr/bin/node server.js
Restart=on-failure          # si se cae, reinícialo
Environment=NODE_ENV=production

[Install]
WantedBy=multi-user.target

⚠️ Restart=on-failure es lo mínimo para un servicio de producción. Y nunca ejecutes servicios como root si no es imprescindible: cada servicio, su usuario.

Logs

journalctl -u nginx -f        # systemd: seguir los logs de un servicio
tail -f /var/log/nginx/access.log
tail -f /var/log/nginx/error.log
grep "5[0-9][0-9]" /var/log/nginx/access.log | tail   # errores 5xx

Servidores: Nginx a mano

Antes de Docker, monta Nginx a mano. Entenderás cada pieza.

Instalación y primeros pasos

apt update && apt install -y nginx
systemctl enable --now nginx
nginx -t            # validar configuración
systemctl reload nginx

Virtual hosts (server blocks)

Cada sitio es un server {} en /etc/nginx/sites-available/ con un symlink en sites-enabled/:

server {
    listen 80;
    server_name miproyecto.com www.miproyecto.com;

    root /var/www/miproyecto;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

Reverse proxy: el patrón que usarás todo el día

Nginx recibe por fuera y reenvía a tu app (Node, PHP-FPM, Go) que escucha en un puerto interno:

server {
    listen 80;
    server_name api.miproyecto.com;

    location / {
        proxy_pass http://127.0.0.1:8080;   # tu app
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
Internet ──▶ :80/:443 Nginx (público) ──▶ 127.0.0.1:8080 app (privado)

💡 Por qué Nginx delante: TLS/HTTPS (certificados), estáticos ultrarrápidos, caché, load balancing, rate limiting, gzip, y tu app no queda expuesta directamente. Detalle en wiki: Nginx.

HTTPS con Let’s Encrypt

apt install certbot python3-certbot-nginx
certbot --nginx -d miproyecto.com -d www.miproyecto.com
# renueva automáticamente con un timer de systemd

Load balancing con Nginx

upstream backend {
    server 10.0.0.1:8080;
    server 10.0.0.2:8080;
    server 10.0.0.3:8080;
}
server {
    listen 80;
    location / {
        proxy_pass http://backend;
    }
}

Redes y seguridad

Resumen de los conceptos y comandos esenciales (a fondo en wiki: Firewalls y Redes y seguridad):

Firewalls: iptables / nftables / UFW

El firewall filtra el tráfico por reglas. UFW es la capa amigable sobre iptables:

ufw default deny incoming      # bloquear todo lo que entra por defecto
ufw allow ssh                  # excepto SSH
ufw allow 80,443/tcp           # y web
ufw enable
ufw status verbose

SSH hardening

# /etc/ssh/sshd_config
Port 22
PermitRootLogin no              # NUNCA root por SSH
PasswordAuthentication no       # solo claves
PubkeyAuthentication yes
AllowUsers ana deploy
ssh-keygen -t ed25519           # genera clave (ed25519 > rsa)
ssh-copy-id ana@servidor        # copia la clave pública al servidor

⚠️ Reglas de oro de SSH: sin login root, sin contraseñas (solo claves), puerto 22 o alterno, y fail2ban para bloquear a los que intentan entrar por fuerza bruta.

fail2ban

apt install fail2ban
fail2ban-client status sshd     # ver IPs baneadas
# banea IPs tras N intentos fallidos de SSH

Infraestructura moderna

Docker: empaquetar y aislar

Docker empaqueta tu app y sus dependencias en una imagen y la ejecuta en un contenedor aislado (mismo kernel que el host, pero con su propio filesystem y procesos).

# Dockerfile
FROM node:22-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
EXPOSE 3000
CMD ["node", "server.js"]
docker build -t miapp .
docker run -d -p 8080:3000 --name app miapp
docker ps
docker logs -f app
docker exec -it app sh

💡 Imagen vs contenedor: la imagen es la receta/plantilla (immutable); el contenedor es la instancia ejecutándose. Compón con docker-compose.yml la app + BBDD + Redis:

# docker-compose.yml
services:
  app:
    build: .
    ports: ["8080:3000"]
    depends_on:
      - db
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: secreto
    volumes:
      - pgdata:/var/lib/postgresql/data
volumes:
  pgdata:

Kubernetes: orquestar contenedores

Kubernetes (k8s) orquesta muchos contenedores: los reparte, los reinicia, escala, balancea, gestiona el estado.

Control plane (brain):          Worker nodes (muscles):
  API server, scheduler,           kubelet, kube-proxy
  etcd (el "cerebro", Raft)        ejecutan pods
Concepto Qué es
Pod La unidad mínima (1+ contenedores juntos)
Deployment «Quiero N réplicas de esta app» (declarativo)
Service IP estable + balanceo a los pods
Ingress Entrada HTTP externa (rutas, TLS)
ConfigMap / Secret Configuración / secretos
etcd El almacén de config del clúster (consenso Raft)
# deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: miapp
spec:
  replicas: 3
  selector:
    matchLabels: { app: miapp }
  template:
    metadata:
      labels: { app: miapp }
    spec:
      containers:
        - name: miapp
          image: miapp:latest
          ports: [{ containerPort: 3000 }]
kubectl apply -f deployment.yaml
kubectl get pods
kubectl rollout status deployment/miapp
kubectl scale deployment miapp --replicas=10
kubectl logs -f deployment/miapp

💡 Declarativo: tú dices el estado deseado («3 réplicas»), Kubernetes hace el trabajo de llegar ahí y mantenerlo. Eso es la esencia de k8s y de Terraform.

Terraform y Ansible

  • Terraform (IaC): declaras la infraestructura (servidores, VPCs, DNS) y Terraform la crea/mantiene/destruye. Infraestructura declarada, no clicada.
resource "aws_instance" "web" {
  ami           = "ami-0c55b159cbfafe1f0"
  instance_type = "t3.micro"
  tags = { Name = "web" }
}
terraform init && terraform plan && terraform apply
  • Ansible: configura los servidores (instala paquetes, copia configs, reinicia servicios) mediante SSH y playbooks en YAML. Agente-less (no instala nada en los servidores).
# playbook.yml
- hosts: web
  tasks:
    - name: Instalar nginx
      apt: name=nginx state=present
    - name: Copiar config
      template: src=default.conf.j2 dest=/etc/nginx/sites-available/default
    - name: Recargar nginx
      service: name=nginx state=reloaded
ansible-playbook -i hosts playbook.yml

CI/CD: integrar y desplegar solos

CI (Continuous Integration): cada push compila, corre tests y analiza. CD (Continuous Delivery/Deployment): si pasa, se despliega.

push ──▶ CI: build + test + lint ──▶ (pasa) ──▶ CD: deploy a staging/prod

Con GitHub Actions:

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: 22 }
      - run: npm ci && npm test
      - run: npm run build

💡 La calidad del CD depende de la de los tests: si tus tests son buenos, desplegar cada merge es seguro (trunk-based + CI verde).

Monitoreo y observabilidad

La observabilidad = 3 pilares:

Pilar Qué responde Herramienta
Métricas ¿Cuánto? (QPS, latencia, errores, CPU) Prometheus + Grafana
Logs ¿Qué pasó? Loki, ELK (Elasticsearch)
Trazas (traces) ¿Dónde tardó? (en qué servicio) Jaeger, OpenTelemetry
Métricas:  HTTP 5xx rate, latencia p95, QPS, uso de CPU/RAM
Logs:      "ERROR: connection to db timed out"
Traces:    petición → gateway → auth → db (55ms en db)

💡 p95/p99: la latencia «típica» engaña. Mide p95 (el 95% de las peticiones tardan menos que esto) y p99: es donde se esconden los problemas reales.

Alertas

Define SLO (objetivo de servicio: «99.9% de peticiones en menos de 500 ms») y alerta cuando lo violas. Si no tienes una métrica de «petición servida correctamente», no puedes saber si tu sistema está sano.

Cloud

Los tres grandes: AWS, GCP, Azure. Conceptos equivalentes en los tres:

Concepto AWS GCP Azure
Servidor virtual EC2 Compute Engine VMs
Contenedores EKS GKE AKS
BBDD gestionada RDS Cloud SQL SQL DB
Almacenamiento S3 GCS Blob
Colas SQS Pub/Sub Queue
Caché ElastiCache Memorystore Cache
Funciones Lambda Cloud Functions Functions

💡 Aprende conceptos, no consolas: una VPC, un balanceador, un object store y una cola existen en los tres. Elige uno (AWS es el más usado) y saca una certificación (Cloud Practitioner → Solutions Architect Associate) como syllabus estructurado.

Cheatsheet de comandos que debes saber

systemctl status/start/restart/reload/enable <svc>
journalctl -u <svc> -f
nginx -t && systemctl reload nginx
ufw status verbose
ss -tulpn                     # puertos en escucha
tail -f /var/log/nginx/*.log
docker ps / logs / exec -it
kubectl get pods / logs -f / apply -f
terraform plan / apply
ansible-playbook playbook.yml

Práctica propuesta

  1. Monta un LEMP a mano (sin Docker): Ubuntu + Nginx + PHP-FPM + MySQL. Sirve un index.php real con conexión a BBDD.
  2. Ponle HTTPS con Let’s Encrypt. Verifica el certificado con curl -v y en el navegador.
  3. Configura ufw para que solo pasen SSH, 80 y 443. Comprueba que no puedes entrar al 8080.
  4. Hardenea SSH: sin root, solo claves, fail2ban. Prueba a entrar con contraseña y verifica que se banea.
  5. Dockeriza una app tuya (Dockerfile + compose con BBDD). Reconstruye la imagen y verifica que el entorno es reproducible.
  6. Crea un pipeline de CI que corra tus tests en cada push (GitHub Actions).
  7. Monta Prometheus + Grafana y grafica la latencia y los 5xx de tu Nginx.
  8. Despliega un sitio en un cloud (el free tier de cualquiera) con Terraform declarando la infra.

Para profundizar

Estudio · Recursos de todo el mundo (inglés, chino, japonés, español, francés, ruso…) curados y traducidos al español.