Nginx在kubernetes上的代理
Nginx在kubernetes上的代理
我在k8s集群中部署了一个代理我的api/
调用的nginx
,配置如下:
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
在搜索了几个小时的互联网后,我找到了一个与这个问题非常相似的文章。我尝试了以下方法:
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上修复这个问题的正确方法是什么?
Nginx在Kubernetes上的代理问题及解决方法
如果API的Pod没有准备好,Nginx将无法将流量路由到它们。
根据Kubernetes文档:
kubelet使用就绪探测来确定容器何时准备好开始接受流量。当所有容器都准备好时,Pod被视为准备就绪。此信号的一个用途是控制用作服务后端的Pod。当一个Pod没有准备好时,它将从服务负载均衡器中移除。
如果您没有使用活性或就绪探测,则即使容器内运行的应用程序尚未完成其启动过程并准备好接受流量,您的Pod也会被标记为“准备就绪”。
关于Pod和DNS记录的相关部分可以在这里找到:
由于Pod名称不会创建A记录,因此Pod的A记录需要主机名。没有主机名但有子域名的Pod只会为无头服务(default-subdomain.my-namespace.svc.cluster-domain.example)创建A记录,指向Pod的IP地址。此外,Pod需要变为准备就绪才能拥有记录,除非在服务上设置publishNotReadyAddresses=True。
更新:我建议将NGINX用作入口控制器。
当您将NGINX用作入口控制器时,NGINX服务成功启动,并且每当部署一个入口规则时,NGINX配置会实时重新加载。
这将帮助您避免NGINX Pod的重新启动。
这是有道理的,但这真的是Nginx无法解析DNS名称的原因吗?
是的,Nginx尝试将从/api路径接收到的流量转发到名为backend-dev的服务,使用Kubernetes内部DNS服务。如果没有支持该服务的Pod,则DNS服务将无法解析任何内容。Kubernetes的Service文档中有关于此的非常详细的信息。
我确实找不到那部分。你能粘贴一下确切的引用吗?
所以,我成功为我的backend-dev服务设置了readinessProbe。尽管如此,负责路由流量到backend-dev的NGINX容器在准备就绪时仍会多次崩溃,并显示相同的错误信息:nginx:[emerg] host not found in upstream "backend-dev" in /etc/nginx/conf.d/default.conf:12。如何解决这个问题?
据我所知,这是预期的行为,因为在那个时候您的服务尚未准备好,没有任何东西来处理传入的流量。你是将NGINX用作入口控制器还是部署NGINX作为服务?您期望的行为是什么?
我更希望不要重新启动Pod。但是如果它最终能够解析backend-dev,那就无所谓了。现在我正在部署NGINX作为负载均衡器服务(计划切换到入口)。这种方法可能修复之前遇到的503错误。我会继续向您报告。
如果您不选择使用入口路径,这篇文章可能对您有帮助。
让我们在聊天室中继续讨论。