import uvicorn
app = FastAPI()
@app.get("/items/{item_id}")
def read_root(item_id: str, request: Request):
client_host = request.client.host
f= open("ipadress.txt","a+")
f.write(client_host+"\n")
f.close()
return {"client_host": client_host, "item_id": item_id}
if __name__ == "__main__":
uvicorn.run(app, host="0.0.0.0", forwarded_allow_ips="*")
The above is the python code which is hosted using uvicorn. When I run the code inside a docker container, it returns the correct client IP. But, when I host the same code on Kubernetes cluster using minikube the IP address which is returned is the localhost IP (127.0.0.1)
The docker command used to run the above code image is
docker run -it -p 8080:8000 <image-name>
I have exposed port 8080 to reach to the service from Virtual Machine
The kubernetes command used to expose the service is
kubectl port-forward --address 0.0.0.0 services/sample-deploy 8080:80
The service.yaml for kubernetes is
apiVersion: v1
kind: Service
metadata:
name: sample-deploy
spec:
type: LoadBalancer
ports:
- port: 80
selector:
app: sample-deploy
I also tried to access the service using LoadBalancer where the service can be accessed using an External IP yet I am not able to get the real client IP address. I think the IP address is masked in the kubernetes cluster.
In the service YAML file, the externalTrafficPolicy should be set to Local so that the IP address is retained. The externalTrafficPolicy can be used only with NodePort or LoadBalancer types.
apiVersion: v1
kind: Service
metadata:
name: sample-deploy
spec:
type: LoadBalancer
externalTrafficPolicy: Local
ports:
- port: 80
selector:
app: sample-deploy
When you do a port-forward
you create a tunnel from your local machine to the container. So, the connection is seen in the container as if it is coming from the local machine (hence the 127.0.0.1
). Port forwarding is usually just used for debugging purposes.
The typical way to access your application would be via a service of type LoadBalancer
or via the Kubernetes ingress concept. In both cases you should get the correct client IP address. For the ingress the client IP is usually provided via a HTTP header (by the ingress load balancer/reverse proxy). Most ingress controllers use X-Forwarded-For
. This header is usually picked up by the web app frameworks when checking for the client IP.