Kubernetes 上的 Nginx 代理
Posted
技术标签:
【中文标题】Kubernetes 上的 Nginx 代理【英文标题】:Nginx proxy on kubernetes 【发布时间】:2019-11-26 05:24:22 【问题描述】:我在 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
pod 没有准备好时,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 返回 502。 还有这个:
location /api
resolver 10.0.0.10 valid=10s;
set $upstreamName backend-dev;
proxy_pass http://$upstreamName/api;
Nginx 返回 503。
在 k8s 上修复它的正确方法是什么?
【问题讨论】:
【参考方案1】:如果您的 API pod 没有准备好,Nginx 将无法将流量路由到它们。
来自 Kubernetes documentation:
kubelet 使用就绪探测来了解容器何时准备好开始接受流量。当 Pod 的所有 Container 都准备好时,就认为 Pod 准备好了。此信号的一种用途是控制哪些 Pod 用作服务的后端。当 Pod 未准备好时,它会从服务负载均衡器中移除。
如果您没有使用 liveness 或 readiness 探针,那么即使您在容器内运行的应用程序尚未完成启动过程并准备好接受流量,您的 pod 也会被标记为“就绪”。
有关 Pod 和 DNS 记录的相关部分可以找到 here
由于没有为 Pod 名称创建 A 记录,因此要创建 Pod 的 A 记录需要 hostname。没有主机名但有子域的 Pod 只会为无头服务创建 A 记录(default-subdomain.my-namespace.svc.cluster-domain.example),指向 Pod 的 IP 地址。此外,Pod 需要准备好才能有记录,除非在 Service 上设置了 publishNotReadyAddresses=True。
更新:我建议使用 NGINX 作为ingress controller。
当您使用 NGINX 作为入口控制器时,NGINX 服务会成功启动,并且无论何时部署 ingress rule,NGINX 配置都是 reloaded on the fly。
这将帮助您避免 NGINX pod 重启。
【讨论】:
有道理,但真的是nginx解析DNS失败的原因吗? 是的,Nginx 尝试使用 kubernetes 内部 DNS 服务将从/api
路径接收到的流量转发到名为backend-dev
的服务。如果没有 Pod 支持该服务,则 DNS 服务将无法解析任何内容。 Kubernetes Service 文档对此有非常详细的信息。
找不到那个部分。能否请您粘贴准确的报价?
我不希望重新启动 pod。但如果它毕竟能够解析backend-dev
,那真的没关系。现在我将 NGINX 部署为负载均衡器服务(在切换到入口的路上)。可能这种方法修复了我之前遇到的 503 错误。我会及时通知你。
如果你不走入口路径,这个post 可能会帮助你。以上是关于Kubernetes 上的 Nginx 代理的主要内容,如果未能解决你的问题,请参考以下文章
在 Kubernetes 的 Nginx Ingress 对象中设置代理通道的最佳方法是啥
在 Kubernetes 上使用 Nginx SSL 代理运行 Meteor 应用程序