Este tema me ha llevado bastante quebraderos de cabeza y hoy voy a explicar qué pasa y como recibir en la cabecera HTTP el X-Forwarded-For.
El objetivo es obtener la IP real del cliente origen cuando tenemos un LoadBalancer de Google Cloud en su Kubernetes con Container Engine. Ya que sino es así todos los logs de Apache/Nginx del backend van a registrar la IP interna del LoadBalancer y no tendremos la IP real del cliente, haciendo imposible por ejemplo la generación de estadísticas reales de visitas.
Cuando levantamos un Service (SVC) de Kubernetes lo hacemos de la siguiente manera:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
apiVersion: v1 kind: Service metadata: name: nginx-back labels: company: Admsistemas spec: type: LoadBalancer ports: - port: 80 name: nginx80 protocol: TCP selector: name: nginx-back |
El «type: LoadBalancer» va aprovisionar un LoadBalancer de la plataforma de GCP directamente a nuestro ReplicationController asignado con el «selector».
Este LoadBalancer va a ser del tipo TCP y ese será el motivo real por el cual no vayamos a recibir la cabecera X-Forwarded-For.
Esto no sucede igual en AWS, que quizás por defecto levantan un LoadBalancer HTTP así que en GCP hay que hacerlo de otro modo.
Así que el objetivo será levantar un LoadBalancer HTTP de la plataforma de GCP, eso lo haremos con Ingress de Kubernetes.
Vamos a modificar nuestro SVC actual cambiando el «type: LoadBalancer» por «type: NodePort«, aplicamos las nuevas configuraciones.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
sysadmin@admsistemas:~$ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.27.240.1 <none> 443/TCP 39d nginx-back 10.27.254.176 104.199.19.129 80/TCP 1m sysadmin@admsistemas:~$ kubectl describe svc nginx-back Name: nginx-back Namespace: default Labels: company=Admsistemas Selector: name=nginx-back Type: LoadBalancer IP: 10.27.254.176 LoadBalancer Ingress: 104.199.19.129 Port: nginx80 80/TCP NodePort: nginx80 31778/TCP Endpoints: 10.24.1.4:80 Session Affinity: None Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 1m 1m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer 49s 49s 1 {service-controller } Normal CreatedLoadBalancer Created load balancer sysadmin@admsistemas:~$ kubectl apply -f nginx-back-svc.yaml service "nginx-back" configured sysadmin@admsistemas:~$ kubectl get svc NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes 10.27.240.1 <none> 443/TCP 39d nginx-back 10.27.254.176 <nodes> 80/TCP 2m sysadmin@admsistemas:~$ kubectl describe svc nginx-back Name: nginx-back Namespace: default Labels: company=Admsistemas Selector: name=nginx-back Type: NodePort IP: 10.27.254.176 Port: nginx80 80/TCP NodePort: nginx80 31778/TCP Endpoints: 10.24.1.4:80 Session Affinity: None Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 4m 4m 1 {service-controller } Normal CreatingLoadBalancer Creating load balancer 3m 3m 1 {service-controller } Normal CreatedLoadBalancer Created load balancer 2m 2m 1 {service-controller } Normal Type LoadBalancer -> NodePort 2m 2m 1 {service-controller } Normal DeletingLoadBalancer Deleting load balancer 1m 1m 1 {service-controller } Normal DeletedLoadBalancer Deleted load balancer |
Ahora ya tenemos un SVC nginx-back que va a ser únicamente accesible desde dentro del clúster de Kubernetes. No tendremos visibilidad desde el exterior.
Para ello vamos a crear un Ingress que va aprovisionar un LoadBalancer HTTP en GCP. Vamos a crear un YAML nuevo: vi nginx-back-ing.yaml
1 2 3 4 5 6 7 8 |
apiVersion: extensions/v1beta1 kind: Ingress metadata: name: nginx-back spec: backend: serviceName: nginx-back servicePort: 80 |
Ahora debemos tener un poco de paciencia para que se aprovisione correctamente el LoadBalancer HTTP e ir observando los cambios.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
sysadmin@admsistemas:~$ kubectl create -f nginx-back-ing.yaml ingress "nginx-back" created sysadmin@admsistemas:~$ kubectl get ing NAME HOSTS ADDRESS PORTS AGE nginx-back * 80 6s # Esperamos un poco mas y ya tendremos IP pública assignada sysadmin@admsistemas:~$ kubectl get ing NAME HOSTS ADDRESS PORTS AGE nginx-back * 130.211.42.153 80 1m sysadmin@admsistemas:~$ kubectl describe ing nginx-back Name: nginx-back Namespace: default Address: 130.211.42.153 Default backend: nginx-back:80 (10.24.1.4:80) Rules: Host Path Backends ---- ---- -------- * * nginx-back:80 (10.24.1.4:80) Annotations: backends: {"k8s-be-31778--8e50d4941921ec0b":"Unknown"} forwarding-rule: k8s-fw-default-nginx-back--8e50d4941921ec0b target-proxy: k8s-tp-default-nginx-back--8e50d4941921ec0b url-map: k8s-um-default-nginx-back--8e50d4941921ec0b Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 1m 1m 1 {loadbalancer-controller } Normal ADD default/nginx-back 28s 28s 1 {loadbalancer-controller } Normal CREATE ip: 130.211.42.153 |
Hasta que la línea «backends» de la sección «Annotations» no aparezca como HEALTHY no será 100% funcional nuestro LoadBalancer HTTP en GCP con Ingress de Kubernetes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
sysadmin@admsistemas:~$ kubectl describe ing nginx-back Name: nginx-back Namespace: default Address: 130.211.42.153 Default backend: nginx-back:80 (10.24.1.4:80) Rules: Host Path Backends ---- ---- -------- * * nginx-back:80 (10.24.1.4:80) Annotations: backends: {"k8s-be-32374--8e50d4941921ec0b":"HEALTHY"} forwarding-rule: k8s-fw-default-nginx-back--8e50d4941921ec0b target-proxy: k8s-tp-default-nginx-back--8e50d4941921ec0b url-map: k8s-um-default-nginx-back--8e50d4941921ec0b Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 18m 18m 1 {loadbalancer-controller } Normal ADD default/nginx-back 17m 17m 1 {loadbalancer-controller } Normal CREATE ip: 130.211.42.153 |