问题

在k8s中使用nginx作为后端接口反向代理,大概配置如下:

  location /api {
      proxy_set_header   X-Forwarded-Proto $scheme;
      proxy_set_header   Host              $http_host;
      proxy_set_header   X-Real-IP         $remote_addr;
      proxy_pass http://api-server-svc:8080/;
  }

其中api-server-svc是后端服务的service
这个配置会有两个问题:

  1. 要求api-server-svc这个service要先创建,否则nginx启动时会因为无法解析api-server-svc而启动失败
  2. nginx服役期间,如果后端服务重启,svc ip改变了,代理会失败,因为nginx缓存了旧ip

解决

修改nginx配置如下:

  # dns设置缓存时间5s,解决问题2
  resolver kube-dns.kube-system.svc.cluster.local valid=5s;
  # 使用变量方式,解决问题1
  set $apiserver api-server-svc.xxx.svc.cluster.local;

  location /api {
      proxy_set_header   X-Forwarded-Proto $scheme;
      proxy_set_header   Host              $http_host;
      proxy_set_header   X-Real-IP         $remote_addr;
      rewrite /api/(.*) /$1 break;
      proxy_pass http://$apiserver:8080;
  }

上述配置文件看起来简单,实际踩了很多坑才研究出来:

坑1

set $apiserver api-server-svc.xxx.svc.cluster.local; 中域名一定要写全域名,不能简写成api-server-svc
之前之所以可以简写,因为容器/etc/resolv.conf中有配置了search,在解析域名时会自动帮你补全域名。
但此处我们使用了resolver指定了域名服务器,在解析时是不会自动帮我们补全的

坑2

使用了proxy_pass http://$apiserver:8080;后,反向代理时url会丢失造成访问404,例如你的请求地址是

http://xxxx/api/a/b/c

代理后只剩下http://xxxx/,所以一定要使用 rewrite /api/(.*) /$1 break;

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐