Skip to content

How to retrieve remote IP in EMK load-balancers

Estimated time to read: 3 minutes

In this tutorial you will learn how to set up a Nginx ingress controller to forward the remote address to a backend service

Preconditions:

  • Fuga Cloud Account
  • Kubectl installed on your machine
  • Helm installed on your machine
  • kubeconfig to access your EMK cluster

Here's a short explanation on what you are going to learn in this tutorial:

  1. Setup Nginx ingress controller
  2. Deploy backend service
  3. Test backend response

Step 1 Setup install Nginx ingress controller

Create a file named values.yaml with the following contents:

---
controller:
  config:
    compute-full-forwarded-for: "true"
    use-forwarded-headers: "true"
    use-proxy-protocol: "true"
  service:
    annotations:
      loadbalancer.openstack.org/proxy-protocol: "true"

This file will instruct Helm to set up the Nginx ingress controller to pass on the remote IP address as an HTTP header to backend services from the load-balancer using the Proxy Protocol.

Install the Nginx ingress controller using a Helm chart:

helm upgrade --install ingress-nginx ingress-nginx \
  --repo https://kubernetes.github.io/ingress-nginx \
  --namespace ingress-nginx --create-namespace \
  --values values.yaml

This will create a new load-balancer with a Floating IP in your EMK cluster:

kubectl -n ingress-nginx get service ingress-nginx-controller
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
ingress-nginx-controller   LoadBalancer   100.68.92.142   81.24.7.20    80:31841/TCP,443:30058/TCP   33m

In this example, any backend service will be available on external IP 81.24.7.20.

Step 2 Deploy backend service

To validate the availability of the remote IP address, deploy an echo server which can respond with a copy of the request including additional headers set by the Nginx ingress controller.

Create a file echoserver.yaml with the following contents:

---
apiVersion: v1
kind: Namespace
metadata:
  name: echoserver
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: echoserver
  namespace: echoserver
spec:
  replicas: 2
  selector:
    matchLabels:
      app: echoserver
  template:
    metadata:
      labels:
        app: echoserver
    spec:
      containers:
      - image: ealen/echo-server:latest
        imagePullPolicy: IfNotPresent
        name: echoserver
        ports:
        - containerPort: 80
        env:
        - name: PORT
          value: "80"
---
apiVersion: v1
kind: Service
metadata:
  name: echoserver
  namespace: echoserver
spec:
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
  type: ClusterIP
  selector:
    app: echoserver
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: echoserver
  namespace: echoserver
  annotations:
    kubernetes.io/ingress.class: nginx
spec:
  rules:
  - host: echoserver.local
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: echoserver
            port:
              number: 80

Deploy the echo server backend containing a Deployment, Service and Ingress:

kubectl apply -f echoserver.yaml

In a production setup you would create proper DNS records in order to resolve the backend service. Instead, instruct your HTTP client to resolve the hostname echoserver.local to the external IP address of the previously created load-balancer. Step 3 Test backend response

Query the echo server backend service using the HTTP client curl with additional resolving information:

curl -s --resolve echoserver.local:80:81.24.7.20 http://echoserver.local | python3 -m json.tool
{
  "request": {
    "headers": {
      "host": "echoserver.local",
      "x-real-ip": "x.x.x.x"
    }
  }
}

The returned JSON object should return the key x-real-ip, equivalent of the HTTP header X-Real-Ip, containing the remote address of the client.

With this setup, your web application should be able to retrieve the remote IP address by parsing the HTTP header X-Real-Ip in the HTTP request.