0%

腾讯云TKE里面获取客户端真实IP

最近服务器都迁移到腾讯云 TKE 了,就是腾讯云 Kubernetes 服务,然后最近有个需求是获取客户端真实 IP。

我的情况:

  • 服务用 Django 写的,通过 HTTP 请求头获取真实 IP
  • Django 通过 uwsgi 运行,并通过 Nginx 转发出去
  • Ingress 使用的 Nginx Ingress,而不是 TKE Ingress

下面说下几个关键配置:

Django 中获取 IP

获取方式如下:

1
2
3
4
5
6
7
def get_client_ip(request):
x_forwarded_for = request.META.get('HTTP_X_FORWARDED_FOR')
if x_forwarded_for:
ip = x_forwarded_for.split(',')[0]
else:
ip = request.META.get('REMOTE_ADDR')
return ip

uwsgi 配置

uwsgi.ini 配置如下:

1
2
3
4
5
6
7
8
[uwsgi]
module = core.wsgi
master = true
processes = 1
vacuum = true
static-map = /static=/app/app/static
http = 127.0.0.1:8000
log-master = true

Nginx 配置

Nginx 需要转发 uwsgi 出去,并且加上三个关键请求头:

1
2
3
4
5
6
7
8
9
10
11
server {
listen 7777;
server_name localhost;

location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_pass http://127.0.0.1:8000;
}
}

Supervisor 配置

Supervisor 需要启动 Uwsgi 和 Nginx:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[supervisord]
nodaemon=true

[program:uwsgi]
command=uwsgi --ini /app/uwsgi.ini
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:nginx]
command=/usr/sbin/nginx -g "pid /run/nginx/nginx.pid; daemon off;"
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

Dockerfile 配置

Dockkerfile 里面指定启动的命令为 supervisor:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
FROM python:3.7-alpine
ENV PYTHONUNBUFFERED 1
WORKDIR /app
COPY requirements.txt .
RUN apk update && apk add \
libuuid \
gcc \
nginx \
supervisor \
libc-dev \
linux-headers \
postgresql-libs \
postgresql-dev \
&& pip install pip -U \
&& pip install -r requirements.txt
COPY . /app
RUN mkdir -p /run/nginx
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY supervisord.conf /etc/supervisord.conf
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]

TKE 配置

这里参考来源为:https://cloud.tencent.com/document/product/457/48949

最关键的就是:

这里我需要修改 Service 的负载均衡:

修改 externalTrafficPolicy 为 Local 即可:

大功告成,后面 IP 就能成功获取到了。