Al implementar Kubernetes en un entorno corporativo o detrás de un firewall, a menudo surge la necesidad de configurar un servidor proxy para acceder a recursos externos. Esto es crítico para la descarga de imágenes de contenedores, la actualización de paquetes y la interacción con APIs externas. En esta guía, abordaremos todos los niveles de configuración de proxy en Kubernetes, desde la configuración de nodos hasta pods individuales.
¿Por qué se necesita un proxy en clústeres de Kubernetes?
Los clústeres de Kubernetes en entornos corporativos a menudo operan en redes aisladas con acceso limitado a Internet. Un servidor proxy resuelve varias tareas críticas:
- Descarga de imágenes de contenedores — Docker Hub, Google Container Registry, registros privados requieren acceso externo
- Actualización de paquetes — instalación de dependencias a través de apt, yum, pip dentro de contenedores
- Acceso a APIs externas — integración con servicios en la nube, monitoreo, registro
- Seguridad — control de tráfico, filtrado de dominios, registro de solicitudes
- Caché — aceleración de solicitudes repetidas a los mismos recursos
Sin una configuración adecuada del proxy, te enfrentarás a errores como "image pull failed", "connection timeout" o "network unreachable" al intentar desplegar aplicaciones. Esto es especialmente crítico para pipelines automáticos de CI/CD, donde cada segundo de inactividad cuesta dinero.
Importante: Para clústeres corporativos, se recomienda utilizar proxies de centros de datos con alta capacidad de ancho de banda y estabilidad de conexión, ya que de ellos depende la operatividad de toda la infraestructura.
Niveles de configuración de proxy en Kubernetes
Kubernetes tiene una arquitectura de múltiples niveles, y el proxy debe configurarse en cada nivel según las tareas:
| Nivel | Qué se configura | Para qué se necesita |
|---|---|---|
| Sistema operativo | Variables de entorno del sistema | Acceso a utilidades (curl, wget, apt) |
| Runtime de contenedores (Docker/containerd) | Configuración del demonio | Descarga de imágenes de contenedores |
| kubelet | Parámetros de inicio de kubelet | Interacción con el servidor API |
| Pods | Variables de entorno en los manifiestos | Acceso de aplicaciones a APIs externas |
| kubectl | Variables de entorno del cliente | Gestión del clúster a través del proxy |
Cada nivel requiere una configuración separada, y omitir cualquiera de ellos puede llevar a problemas. Por ejemplo, si configuras el proxy solo para Docker, pero no para los pods, las imágenes se descargarán, pero las aplicaciones dentro de los contenedores no podrán acceder a las APIs externas.
Configuración de proxy para Docker y containerd
El runtime de contenedores es el primer componente que debe configurarse, ya que es el responsable de descargar imágenes de contenedores de registros externos. Veamos la configuración para ambos runtimes populares.
Configuración de proxy para Docker
Para Docker, necesitas crear un archivo drop-in de systemd que agregue las variables de entorno al servicio de Docker:
# Creamos el directorio para la configuración
sudo mkdir -p /etc/systemd/system/docker.service.d
# Creamos el archivo con la configuración del proxy
sudo tee /etc/systemd/system/docker.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc"
EOF
# Recargamos la configuración de systemd
sudo systemctl daemon-reload
# Reiniciamos Docker
sudo systemctl restart docker
# Verificamos que la configuración se haya aplicado
sudo systemctl show --property=Environment docker
Después de esto, Docker podrá descargar imágenes a través del servidor proxy. Puedes verificar su funcionamiento con el siguiente comando:
docker pull nginx:latest
Configuración de proxy para containerd
Containerd se utiliza en clústeres modernos de Kubernetes como el runtime principal de contenedores. La configuración del proxy para él es un poco diferente:
# Creamos el directorio para la configuración
sudo mkdir -p /etc/systemd/system/containerd.service.d
# Creamos el archivo con la configuración del proxy
sudo tee /etc/systemd/system/containerd.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.cluster.local,.svc"
EOF
# Recargamos la configuración
sudo systemctl daemon-reload
sudo systemctl restart containerd
# Verificamos el estado
sudo systemctl status containerd
Consejo: Si utilizas un registro de contenedores privado, agrega su dominio a NO_PROXY para evitar retrasos innecesarios y problemas con certificados SSL.
Configuración de proxy para kubelet
Kubelet es el agente de Kubernetes que se ejecuta en cada nodo del clúster. También necesita acceso al servidor API y a recursos externos. La configuración depende de la forma en que se instale Kubernetes.
Para clústeres kubeadm
Si utilizas kubeadm, configura el proxy a través de systemd:
# Creamos el directorio para la configuración de kubelet
sudo mkdir -p /etc/systemd/system/kubelet.service.d
# Creamos el archivo con la configuración del proxy
sudo tee /etc/systemd/system/kubelet.service.d/http-proxy.conf <<EOF
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,10.96.0.0/12,10.244.0.0/16,.cluster.local,.svc"
EOF
# Recargamos kubelet
sudo systemctl daemon-reload
sudo systemctl restart kubelet
Para Kubernetes administrados (EKS, GKE, AKS)
En servicios de Kubernetes administrados, la configuración de kubelet generalmente se realiza a través de parámetros de inicio de nodos o scripts de datos de usuario. Por ejemplo, para AWS EKS:
#!/bin/bash
# Script de datos de usuario para nodos de trabajo de EKS
# Configuración del proxy para el sistema
cat <<EOF >> /etc/environment
HTTP_PROXY=http://proxy.company.com:8080
HTTPS_PROXY=http://proxy.company.com:8080
NO_PROXY=localhost,127.0.0.1,169.254.169.254,.ec2.internal,.cluster.local
EOF
# Configuración para kubelet
mkdir -p /etc/systemd/system/kubelet.service.d
cat <<EOF > /etc/systemd/system/kubelet.service.d/http-proxy.conf
[Service]
Environment="HTTP_PROXY=http://proxy.company.com:8080"
Environment="HTTPS_PROXY=http://proxy.company.com:8080"
Environment="NO_PROXY=localhost,127.0.0.1,169.254.169.254,.ec2.internal,.cluster.local"
EOF
systemctl daemon-reload
systemctl restart kubelet
Presta atención a la adición de 169.254.169.254 en NO_PROXY — esta es la dirección del servicio de metadatos de AWS, que debe estar accesible sin proxy.
Configuración de proxy a nivel de pods
Incluso si has configurado el proxy para Docker y kubelet, las aplicaciones dentro de los pods no utilizarán automáticamente el proxy. Debes especificar explícitamente las variables de entorno en los manifiestos de Kubernetes.
Configuración a través del manifiesto de Deployment
La forma más sencilla es agregar las variables de entorno en la especificación del contenedor:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: app
image: my-company/my-app:latest
env:
- name: HTTP_PROXY
value: "http://proxy.company.com:8080"
- name: HTTPS_PROXY
value: "http://proxy.company.com:8080"
- name: NO_PROXY
value: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
ports:
- containerPort: 8080
Uso de ConfigMap para configuración centralizada
Para no duplicar la configuración del proxy en cada Deployment, crea un ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: proxy-config
namespace: default
data:
HTTP_PROXY: "http://proxy.company.com:8080"
HTTPS_PROXY: "http://proxy.company.com:8080"
NO_PROXY: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
Luego, utiliza este ConfigMap en el Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
spec:
template:
spec:
containers:
- name: app
image: my-company/my-app:latest
envFrom:
- configMapRef:
name: proxy-config
Este enfoque simplifica la gestión: al cambiar la dirección del proxy, solo necesitas actualizar el ConfigMap, y después de reiniciar los pods, se aplicarán automáticamente las nuevas configuraciones.
Inyección automática a través de MutatingWebhook
Para agregar automáticamente las variables del proxy a todos los pods, se puede usar MutatingAdmissionWebhook. Este es un enfoque avanzado que requiere el desarrollo de un servicio webhook propio, pero permite gestionar centralizadamente la configuración sin modificar los manifiestos de las aplicaciones.
Configuración correcta de NO_PROXY
La variable NO_PROXY define qué direcciones y dominios deben evitar el servidor proxy. Una configuración incorrecta de NO_PROXY es la causa más común de problemas en clústeres de Kubernetes.
Excepciones obligatorias para Kubernetes
Las siguientes direcciones y rangos DEBEN estar SIEMPRE en NO_PROXY:
| Dirección/Rango | Propósito |
|---|---|
localhost, 127.0.0.1 |
Conexiones locales |
.cluster.local |
DNS interno del clúster |
.svc |
Servicios de Kubernetes |
10.0.0.0/8 |
Red de Pods (depende de CNI) |
10.96.0.0/12 |
Red de servicios (por defecto) |
172.16.0.0/12 |
Redes privadas de Docker |
192.168.0.0/16 |
Redes locales privadas |
Ejemplo de configuración completa de NO_PROXY
NO_PROXY=localhost,127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.96.0.0/12,.cluster.local,.svc,.default.svc,.default.svc.cluster.local,kubernetes.default.svc,kubernetes.default.svc.cluster.local
Advertencia: Algunas aplicaciones no soportan la notación CIDR en NO_PROXY. En tales casos, utiliza comodines: 10.* en lugar de 10.0.0.0/8.
Configuración de kubectl para trabajar a través de un proxy
Si gestionas un clúster desde una estación de trabajo que está detrás de un proxy, configura las variables de entorno para kubectl:
# Para Linux/macOS - agrega a ~/.bashrc o ~/.zshrc
export HTTP_PROXY=http://proxy.company.com:8080
export HTTPS_PROXY=http://proxy.company.com:8080
export NO_PROXY=localhost,127.0.0.1,kubernetes.default.svc,.cluster.local
# Para Windows PowerShell
$env:HTTP_PROXY="http://proxy.company.com:8080"
$env:HTTPS_PROXY="http://proxy.company.com:8080"
$env:NO_PROXY="localhost,127.0.0.1,kubernetes.default.svc,.cluster.local"
Después de esto, kubectl podrá conectarse al servidor API del clúster a través del proxy. Verifica su funcionamiento:
kubectl cluster-info
kubectl get nodes
Configuración de proxy con autenticación
Si el servidor proxy requiere autenticación, agrega las credenciales en la URL:
export HTTP_PROXY=http://username:password@proxy.company.com:8080
export HTTPS_PROXY=http://username:password@proxy.company.com:8080
Seguridad: No almacenes contraseñas en texto claro en archivos de configuración. Utiliza variables de entorno o secretos de Kubernetes para almacenar credenciales del proxy.
Diagnóstico y solución de problemas comunes
Incluso con la configuración correcta, pueden surgir problemas. Veamos los errores más comunes y cómo solucionarlos.
Error "ImagePullBackOff" al descargar imágenes
Síntomas: Los pods no se inician, en los eventos aparece el error "Failed to pull image" o "connection timeout".
Diagnóstico:
# Verifica los eventos del pod
kubectl describe pod <pod-name>
# Verifica la configuración del proxy en Docker/containerd
sudo systemctl show --property=Environment docker
sudo systemctl show --property=Environment containerd
# Intenta descargar la imagen manualmente en el nodo
sudo docker pull nginx:latest
sudo crictl pull nginx:latest
Solución: Asegúrate de que el proxy esté configurado para el runtime de contenedores y que el dominio del registro de imágenes no esté en NO_PROXY.
Problemas con la resolución DNS dentro del clúster
Síntomas: Los pods no pueden comunicarse entre sí por nombres DNS (por ejemplo, service-name.namespace.svc.cluster.local).
Diagnóstico:
# Verifica DNS desde el pod
kubectl run -it --rm debug --image=busybox --restart=Never -- nslookup kubernetes.default
# Verifica las variables del proxy en el pod
kubectl exec -it <pod-name> -- env | grep PROXY
Solución: Agrega .cluster.local y .svc en NO_PROXY.
Trabajo lento o timeouts al acceder a APIs externas
Síntomas: Las aplicaciones funcionan lentamente o reciben timeouts al hacer solicitudes a servicios externos.
Diagnóstico:
# Verifica la disponibilidad del proxy desde el pod
kubectl exec -it <pod-name> -- curl -v -x http://proxy.company.com:8080 https://www.google.com
# Mide el tiempo de respuesta
kubectl exec -it <pod-name> -- time curl -x http://proxy.company.com:8080 https://api.example.com
Solución: El problema puede estar en el rendimiento del servidor proxy. Considera usar proxies residenciales con ubicación geográfica cercana para reducir latencias.
Errores SSL/TLS al trabajar a través del proxy
Síntomas: Errores como "certificate verify failed" o "SSL handshake failed".
Causa: Algunos servidores proxy realizan inspección SSL (descifrado del tráfico HTTPS), lo que requiere la instalación del certificado raíz del proxy.
Solución:
# Crea un ConfigMap con el certificado del proxy
kubectl create configmap proxy-ca-cert --from-file=ca.crt=/path/to/proxy-ca.crt
# Monta el certificado en el pod y añádelo al almacén de certificados del sistema
apiVersion: apps/v1
kind: Deployment
spec:
template:
spec:
containers:
- name: app
volumeMounts:
- name: proxy-ca
mountPath: /usr/local/share/ca-certificates/proxy-ca.crt
subPath: ca.crt
volumes:
- name: proxy-ca
configMap:
name: proxy-ca-cert
Mejores prácticas para proxies en producción
Basado en la experiencia de operar clústeres de Kubernetes en un entorno corporativo, aquí hay recomendaciones para un funcionamiento confiable con proxies:
1. Utiliza servidores proxy de alta disponibilidad
El proxy se convierte en un único punto de falla para todo el clúster. Configura varios servidores proxy detrás de un balanceador de carga:
HTTP_PROXY=http://proxy-lb.company.com:8080
Donde proxy-lb.company.com es el balanceador de carga frente a varios servidores proxy.
2. Gestión centralizada de la configuración
Utiliza ConfigMap o Secret para almacenar configuraciones de proxy en lugar de codificarlas en cada manifiesto:
apiVersion: v1
kind: ConfigMap
metadata:
name: cluster-proxy-config
namespace: kube-system
data:
HTTP_PROXY: "http://proxy-lb.company.com:8080"
HTTPS_PROXY: "http://proxy-lb.company.com:8080"
NO_PROXY: "localhost,127.0.0.1,.cluster.local,.svc,10.0.0.0/8"
3. Monitoreo y alertas
Configura el monitoreo de la disponibilidad de los servidores proxy y alertas ante problemas:
- Tiempo de respuesta del proxy (debe ser < 100ms para proxies locales)
- Número de errores de conexión al proxy
- Número de eventos ImagePullBackOff en el clúster
- Carga de CPU y red en los servidores proxy
4. Documenta las excepciones de NO_PROXY
Mantén documentación sobre qué dominios y direcciones IP se han agregado a NO_PROXY y por qué. Esto ayudará en la solución de problemas y auditoría de seguridad.
5. Prueba los cambios en un entorno de desarrollo
Antes de cambiar la configuración del proxy en producción, siempre prueba en un clúster de desarrollo/staging:
# Pod de prueba para verificar el proxy
apiVersion: v1
kind: Pod
metadata:
name: proxy-test
spec:
containers:
- name: test
image: curlimages/curl:latest
command: ["sleep", "3600"]
env:
- name: HTTP_PROXY
value: "http://new-proxy.company.com:8080"
- name: HTTPS_PROXY
value: "http://new-proxy.company.com:8080"
# Verifica la disponibilidad de recursos externos
kubectl exec -it proxy-test -- curl -v https://registry.k8s.io
kubectl exec -it proxy-test -- curl -v https://docker.io
6. Utiliza diferentes tipos de proxies para diferentes tareas
Para componentes críticos (descarga de imágenes, API del clúster), utiliza proxies rápidos de centros de datos, y para aplicaciones que requieren diversidad geográfica de IP, utiliza proxies residenciales o móviles.
7. Actualiza regularmente la lista de NO_PROXY
Al agregar nuevos servicios o cambiar la topología de la red, actualiza NO_PROXY. Automatiza esto a través de Helm charts o Kustomize:
# values.yaml para Helm chart
proxy:
enabled: true
http: "http://proxy.company.com:8080"
https: "http://proxy.company.com:8080"
noProxy:
- localhost
- 127.0.0.1
- .cluster.local
- .svc
- 10.0.0.0/8
- internal-service.company.com
Conclusión
La configuración de proxy en clústeres de Kubernetes es una tarea de múltiples niveles que requiere atención a los detalles en cada nivel: desde el sistema operativo y el runtime de contenedores hasta los pods individuales. Una configuración adecuada garantiza el funcionamiento ininterrumpido del clúster, el acceso seguro a recursos externos y el cumplimiento de las políticas de seguridad corporativas.
Puntos clave a recordar:
- Configura el proxy en todos los niveles: SO, runtime de contenedores, kubelet, pods
- Configura correctamente NO_PROXY, incluyendo todas las redes internas del clúster
- Utiliza gestión centralizada a través de ConfigMap
- Monitorea la disponibilidad y el rendimiento de los servidores proxy
- Prueba los cambios antes de aplicarlos en producción
Para clústeres de Kubernetes críticos, recomendamos utilizar proxies de centros de datos confiables con alta disponibilidad y baja latencia. Esto garantizará un funcionamiento estable de la infraestructura y minimizará los riesgos de inactividad debido a problemas de acceso a la red.
Al enfrentar problemas, utiliza un enfoque sistemático para el diagnóstico: verifica la configuración en cada nivel, analiza los registros y eventos, prueba la conexión manualmente. La mayoría de los problemas con proxies en Kubernetes se resuelven con la configuración adecuada de las variables de entorno y NO_PROXY.