Implementación de Ingress con Traefik en Clúster Kubernetes

Introducción al Balanceo de Carga de Capa 7

Los servicios de Kubernetes, tanto ClusterIP como NodePort, operan exculsivamente en la capa de transporte (L4). Para lograr balanceo de carga basado en HTTP/HTTPS y routing avanzado, es necesario implementar un controlador de Ingress que funcione en la capa 7 del modelo OSI. Existen múltiples implementaciones disponibles: NGINX, Contour, HAProxy, Traefik y Istio, cada una con características distintivas.

Componentes Principales de Ingress-NGINX

  • controlador-ingress: Procesa las reglas definidas en objetos Ingress y actualiza dinámicamente la configuración del servidor web mediante scripts automatizados
  • Objeto Ingress: Representa abstracción para mapear tráfico externo a servicios internos según dominio y ruta URL
  • Controlador: Componente responsable de escuchar sockets y enrutar solicitudes siguiendo políticas definidas en recursos Ingress

Las ventajas clave incluyen consolidación de puertos expuestos (un solo punto de entrada), gestión centralizada mediante nombres de dominio y simplificación en el escalado de nuevas aplicaciones sin modificaciones adicionales de infraestructura.

Estructura de Infraestructura

Servidor Función Dirección IP Rol
node-primary.cluster.local Ingress Controller + Traefik 192.168.10.21 Nodo Worker
node-secondary.cluster.local Ingress Controller + Traefik 192.168.10.22 Nodo Worker
loadbalancer-dns.cluster.local Balanceador L7 + DNS 192.168.10.11 Máquina Proxy
loadbalancer-cluster.cluster.local Balanceador L7 192.168.10.12 Máquina Proxy
admin-host.cluster.local Despliegue de Manifiestos 192.168.10.200 Servidor Operaciones

Preparación del Contenedro Traefik

# En servidor admin-host.cluster.local
docker pull traefik:v1.7-alpine
docker tag a8b4c9d0e1f2 registry.corp.internal/k8s/traefik:v1.7-enterprise
docker push registry.corp.internal/k8s/traefik:v1.7-enterprise

Catálogo de Recursos

mkdir -p /k8s-manifests/traefik-proxy && cd /k8s-manifests/traefik-proxy

Configuración RBAC

cat > /k8s-manifests/traefik-proxy/rbac-config.yaml <<'EOF'
apiVersion: v1
kind: ServiceAccount
metadata:
  name: traefik-service-account
  namespace: kube-system
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: traefik-role-access
rules:
  - apiGroups: [""]
    resources: ["services", "endpoints", "secrets"]
    verbs: ["get", "list", "watch"]
  - apiGroups: ["extensions"]
    resources: ["ingresses"]
    verbs: ["get", "list", "watch"]
---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: traefik-binding
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: traefik-role-access
subjects:
- kind: ServiceAccount
  name: traefik-service-account
  namespace: kube-system
EOF

Manifiesto DaemonSet

cat > /k8s-manifests/traefik-proxy/deployment-traefik.yaml <<'EOF'
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: traefik-proxy-controller
  namespace: kube-system
  labels:
    app-label: traefik-lb
spec:
  selector:
    matchLabels:
      app-label: traefik-lb
  template:
    metadata:
      labels:
        app-label: traefik-lb
        pod-name: traefik-lb
    spec:
      serviceAccountName: traefik-service-account
      terminationGracePeriodSeconds: 60
      containers:
      - image: registry.corp.internal/k8s/traefik:v1.7-enterprise
        name: traefik-lb-container
        ports:
        - name: ingress-http
          containerPort: 80
          hostPort: 8080
        - name: dashboard-port
          containerPort: 8080
          hostPort: 9090
        securityContext:
          capabilities:
            drop:
            - ALL
            add:
            - NET_BIND_SERVICE
        args:
        - --api
        - --kubernetes
        - --logLevel=INFO
        - --insecureskipverify=true
        - --kubernetes.endpoint=https://192.168.10.10:7443
        - --accesslog
        - --accesslog.filepath=/var/log/traefik-access.log
        - --traefiklog
        - --traefiklog.filepath=/var/log/traefik-server.log
        - --metrics.prometheus
      imagePullSecrets:
      - name: registry-auth
EOF

El puerto 8080 en hostPort permite exposición directa del servicio de Ingress desde los nodos workers.

Instalación del Controlador

kubectl apply -f http://k8s-manifests.registry.internal/traefik-proxy/rbac-config.yaml
kubectl apply -f http://k8s-manifests.registry.internal/traefik-proxy/deployment-traefik.yaml

Manifiesto de Servicio de Prueba

cat > /k8s-manifests/nginx-demo/svc-definition.yaml <<'EOF'
apiVersion: v1
kind: Service
metadata:
  annotations:
    k8s-app: web-test-service
  name: web-test-svc
  namespace: default
spec:
  ports:
    - port: 80
      protocol: TCP
      targetPort: 80
  selector:
    application: web-test-app
  sessionAffinity: None
EOF

Definición de Ingress

cat > /k8s-manifests/nginx-demo/route-ingress.yaml <<'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: web-application-route
  namespace: default
  annotations:
    ingress-class: traefik
spec:
  rules:
  - host: webapp.demo.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-test-svc
            port:
              number: 80
EOF

Despliegue de Aplicación Backend

cat > /k8s-manifests/nginx-demo/app-deployment.yaml <<'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-test-app
  labels:
    application: web-test-app
spec:
  replicas: 3
  selector:
    matchLabels:
      application: web-test-app
  template:
    metadata:
      labels:
        application: web-test-app
    spec:
      containers:
      - name: nginx-server
        image: registry.corp.internal/public/nginx:v1.19-alpine
        ports:
        - name: http-port
          containerPort: 80
EOF

Configuración DNS

# En loadbalancer-dns.cluster.local
echo "webapp               A    192.168.10.10" >> /etc/bind/zones/demo.com.zone
sed -i 's/serial [0-9]*/serial '$(date +%Y%m%d%H%M)'/' /etc/bind/zones/demo.com.zone
systemctl restart bind9

Balanceador de Carga Externo NGINX

# En ambos servidores proxy
cat > /etc/nginx/conf.d/webapp-backend.conf <<'EOF'
upstream traefik_backend_pool {
    server 192.168.10.21:8080 weight=1 max_fails=3 fail_timeout=10s;
    server 192.168.10.22:8080 weight=1 max_fails=3 fail_timeout=10s;
}

server {
    listen 80;
    server_name webapp.demo.com;
    
    location / {
        proxy_pass http://traefik_backend_pool;
        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;
    }
}
EOF
nginx -s reload

Aplicación de Recursos

kubectl apply -f http://k8s-manifests.registry.internal/nginx-demo/app-deployment.yaml
kubectl apply -f http://k8s-manifests.registry.internal/nginx-demo/svc-definition.yaml  
kubectl apply -f http://k8s-manifests.registry.internal/nginx-demo/route-ingress.yaml

Verificación de Estado

kubectl get ing -n default
NAME                 CLASS    HOSTS             ADDRESS   PORTS   AGE
web-application-route         webapp.demo.com            80      2h

kubectl get pods -n kube-system -o wide | grep traefik
traefik-proxy-controller-pod-abc     1/1     Running   0         1d   10.244.10.5   node-primary.cluster.local   <none>
traefik-proxy-controller-pod-def     1/1     Running   0         1d   10.244.10.6   node-secondary.cluster.local  <none>

Personalización Contenido Web

kubectl exec -it $(kubectl get pods -l application=web-test-app -o jsonpath='{.items[0].metadata.name}') -- sh -c "echo <h1>Servidor 1</h1> > /usr/share/nginx/html/index.html"
kubectl exec -it $(kubectl get pods -l application=web-test-app -o jsonpath='{.items[1].metadata.name}') -- sh -c "echo <h1>Servidor 2</h1> > /usr/share/nginx/html/index.html"

Etiquetas: Kubernetes Traefik ingress DaemonSet rbac

Publicado el 10-7 21:55