kubernetes 上的 Nginx 代理

Nginx proxy on kubernetes

我在 k8s 集群中有一个 nginx 部署,它代理我的 api/ 调用,如下所示:

server {
  listen 80;

  location / {
    root /usr/share/nginx/html;
    index index.html index.htm;
    try_files $uri $uri/ /index.html =404;
  }

  location /api {
    proxy_pass http://backend-dev/api;
  }
}

这在大多数情况下都有效,但是有时当 api pods 没有准备好时,nginx 会失败并出现错误:

nginx: [emerg] host not found in upstream "backend-dev" in /etc/nginx/conf.d/default.conf:12

在浏览互联网几个小时后,我发现 article 这几乎是同一个问题。我试过这个:

  location /api {
    set $upstreamName backend-dev;
    proxy_pass http://$upstreamName/api;
  }

现在nginx returns 502。 还有这个:

  location /api {
    resolver 10.0.0.10 valid=10s;
    set $upstreamName backend-dev;
    proxy_pass http://$upstreamName/api;
  }

Nginx returns 503.

在 k8s 上修复它的正确方法是什么?

如果您的 API pods 没有准备好,Nginx 将无法将流量路由到它们。

来自 Kubernetes documentation:

The kubelet uses readiness probes to know when a Container is ready to start accepting traffic. A Pod is considered ready when all of its Containers are ready. One use of this signal is to control which Pods are used as backends for Services. When a Pod is not ready, it is removed from Service load balancers.

如果您没有使用活性或就绪探测,那么您的 pod 将被标记为 "ready",即使容器内的应用程序 运行 尚未完成其启动过程并准备好接受交通.

可以找到关于 Pods 和 DNS 记录的相关部分 here

Because A records are not created for Pod names, hostname is required for the Pod’s A record to be created. A Pod with no hostname but with subdomain will only create the A record for the headless service (default-subdomain.my-namespace.svc.cluster-domain.example), pointing to the Pod’s IP address. Also, Pod needs to become ready in order to have a record unless publishNotReadyAddresses=True is set on the Service.

更新: 我建议使用 NGINX 作为 ingress controller.

当您使用 NGINX 作为入口控制器时,NGINX 服务会成功启动,并且每当 ingress rule is deployed, the NGINX configuration is reloaded on the fly.

这将帮助您避免 NGINX pod 重启。