Trong quá trình vận hành hệ thống kubernetes mình gặp phải vấn đề lấy real IP của client (lấy ip của client gửi request đến cụm). Cụm k8s (kubernetes xin phép gọi tắt cho gọn) của mình đang sử dụng version v1.13.11
và dùng nginx-ingress version v0.26.1
.
Dưới đây là flow tổng quát case đầu tiên mình gặp phải.

Domain abc.com trỏ vào public ip của một con nginx làm reverse proxy. Con này là 1 con server không nằm trên cụm k8s, tất cả request đến con proxy đều được forward về service của nginx-ingress. Vấn đề là làm sao trong các pod từ 1 đến 3 mình có thể lấy đc ip của User khi họ request vào domain abc.com. Mình sẽ chạy thử một ví dụ để mô tả trường hợp trên.
Tạo một deployment demo:
kubectl create deployment source-ip-app --image=k8s.gcr.io/echoserver:1.4
Tạo service của deployment:
kubectl expose deployment source-ip-app --port 8080
Kiểm tra trạng thái deployment và service:
kubectl get pod Output: NAME READY STATUS RESTARTS AGE source-ip-app-5bf59f5b75-fnqxn 1/1 Running 0 2m56s kubectl get svc Output NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE kubernetes ClusterIP 10.10.0.1 <none> 443/TCP 130d source-ip-app ClusterIP 10.10.28.159 <none> 80/TCP 2m32s
Tạo ingress:
kubectl create -f - <<EOF apiVersion: extensions/v1beta1 kind: Ingress metadata: annotations: kubernetes.io/ingress.allow-http: "true" kubernetes.io/ingress.class: nginx name: source-ip-app spec: rules: - host: abc.hocdevops.com http: paths: - backend: serviceName: source-ip-app servicePort: 8080 path: / EOF
Check lại xem domain work chưa:
curl -I -v http://abc.hocdevops.com Output: CLIENT VALUES: client_address=10.9.1.174 command=GET real path=/ query=nil request_version=1.1 request_uri=http://abc.hocdevops.com:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 accept-encoding=gzip, deflate, br accept-language=en-GB,en;q=0.9,vi-VN;q=0.8,vi;q=0.7,en-US;q=0.6 cache-control=max-age=0 cookie=lastSignedIn=google; sessions=%7B%7D; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1 dnt=1 host=test.goquo.io http-x-forwarded-for=38.xxx.xxx.xxx http-x-forwarded-proto=https sec-fetch-mode=navigate sec-fetch-site=none sec-fetch-user=?1 upgrade-insecure-requests=1 user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36 x-forwarded-for=53.xxx.xxx.xxx x-forwarded-host=abc.hocdevops.com x-forwarded-port=80 x-forwarded-proto=http x-forwarded-ssl=on x-original-forwarded-for=38.xxx.xxx.xxx x-real-ip=53.xxx.xxx.xxx x-request-id=319da13ab129ab790cdcb9b49a723ef3 x-scheme=http BODY: -no body in request-
Logic của code là sẽ lấy Real IP qua header x-real-ip
Chúng ta có thể thấy x-real-ip
là ip của prõy không phải là ip của user. Để xử lý issue này chúng ta sửa configmap của nginx ingress 1 chút:
kubectl edit cm nginx-configuration -n ingress-nginx # Thêm đoạn config sau vào cuối file data: compute-full-forwarded-for: "true" use-forwarded-headers: "true"
Kiểm tra lại lần nữa xem đã được chưa này:
curl -I -v http://abc.hocdevops.com Output: CLIENT VALUES: client_address=10.9.1.174 command=GET real path=/ query=nil request_version=1.1 request_uri=http://abc.hocdevops.com:8080/ SERVER VALUES: server_version=nginx: 1.10.0 - lua: 10001 HEADERS RECEIVED: accept=text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9 accept-encoding=gzip, deflate, br accept-language=en-GB,en;q=0.9,vi-VN;q=0.8,vi;q=0.7,en-US;q=0.6 cache-control=max-age=0 cookie=lastSignedIn=google; sessions=%7B%7D; SL_GWPT_Show_Hide_tmp=1; SL_wptGlobTipTmp=1 dnt=1 host=test.goquo.io http-x-forwarded-for=38.xxx.xxx.xxx http-x-forwarded-proto=https sec-fetch-mode=navigate sec-fetch-site=none sec-fetch-user=?1 upgrade-insecure-requests=1 user-agent=Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36 x-forwarded-for=38.xxx.xxx.xxx,53.xxx.xxx.xxx x-forwarded-host=abc.hocdevops.com x-forwarded-port=80 x-forwarded-proto=http x-forwarded-ssl=on x-original-forwarded-for=38.xxx.xxx.xxx x-real-ip=38.xxx.xxx.xxx x-request-id=319da13ab129ab790cdcb9b49a723ef3 x-scheme=http BODY: -no body in request-
Có thể thấy chúng ta đã lấy được Real IP của User dựa vào header x-real-ip
.