技术之道

长风破浪会有时,直挂云帆济沧海

  • 首页
  • 分类
  • 归档
  • 标签

  • 搜索
服务治理 k8s tabnine cursor github copilot ai chatgpt chatgpt ai sop 技术选型 bigdata 工具 多进程多线程 docker 计算机网络 mysql 事务 基础架构 kafka nio 分布式 服务搭建 监控 jvm 管理/成长 jenkins devops 云原生 nginx 架构 故障处理 hive spark mapreduce apm redis memcached java 性能 linux

在k8s中Nginx不能解析hostname

发表于 2024-08-13 | 分类于 云原生 | 0 | 阅读次数 437

在k8s中Nginx不能解析hostname

1. 简介

1.1 目的

本文档旨在描述 Kubernetes 环境中 Nginx 无法解析 hostname 的问题,提供可能的原因分析、排查步骤以及解决方案,帮助运维人员和开发人员快速解决该问题。

1.2 适用范围

本文档适用于在 Kubernetes 集群中部署 Nginx 作为反向代理或前端服务器,并遇到无法解析 hostname 问题的场景。

1.3 相关人员

运维人员、开发人员和技术支持人员

2. 问题描述

2.1 问题场景

​ 在 Kubernetes 集群中,Nginx 通常用于接收和处理外部请求,并将这些请求代理到内部服务。然而,有时 Nginx 无法解析指定的 hostname,导致无法将请求正确路由到目标服务或外部资源。例如,下面的配置示例展示了一个常见的 Nginx 配置:

server {
    listen 80;
    server_name _;
    index index.jsp index.html index.htm index.php default.html default.htm default.php;
    root  /usr/share/nginx/html/;

    client_max_body_size 500m;
    proxy_buffering    on;
    proxy_buffer_size  4k;
    proxy_buffers 4  8k;
    proxy_busy_buffers_size 12k;

    access_log /dev/stdout main;
    error_log /dev/stderr info;

    location / {
				try_files $uri $uri/ /index.html;
	  }

    location /backend/ {
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;

        proxy_read_timeout 60s;
        proxy_set_header Connection "";
        proxy_connect_timeout 60;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://td-ba-coding-devops-guide-prod.prod.svc.cluster.local:80?$query_string;
	}

}

在这种配置下,当客户端访问 /backend/ URL 时,可能会出现如下错误:

[error] 9#9: *5 no resolver defined to resolve td-ba-coding-devops-guide-prod.prod.svc.cluster.local, client: 10.20.102.253, server: _, request: "GET /backend?hi=11 HTTP/1.1", host: "coding-devops-guide.teddymobile.net"

此错误表明 Nginx 无法解析 td-ba-coding-devops-guide-prod.prod.svc.cluster.local 这个 hostname,导致请求无法正确转发到后端服务。可使用kubectl exec -it ** -- nslookup命令查询svc在k8s中的域名的 DNS 记录时,发现是可以正确解析到相应的IP地址:

2.2 问题原因分析

  1. Kubernetes DNS 服务工作原理

    在 Kubernetes 集群中,CoreDNS 负责处理所有内部服务的 DNS 解析请求。当 Nginx 作为前端服务器使用时,需要通过 CoreDNS 来解析集群内其他服务的 hostname,以及处理外部域名解析请求。因此,CoreDNS 的正确配置对于 Nginx 能否正常解析 hostname 至关重要。

  2. Nginx 配置中的 hostname 解析逻辑

    Nginx 使用 resolver 指令来指定要使用的 DNS 服务器,以解析配置文件中定义的 hostname。如果 resolver 指令未正确配置,或者未指定合适的 DNS 服务器,Nginx 将无法解析 hostname,从而导致请求失败。

  3. 常见的 DNS 配置错误

    • CoreDNS 配置问题: CoreDNS 配置文件中的错误可能会导致 DNS 解析失败。例如,缺少必要的 upstream 配置可能会导致无法正确解析外部域名。
    • Nginx 配置错误: 如果 Nginx 配置文件中的 resolver 指令没有指定正确的 DNS 服务器,或者指定了错误的 IP 地址,Nginx 将无法解析 hostname。这可能导致内部服务之间的通信问题,或者导致无法解析外部域名。

3. 排查步骤

3.1 检查 DNS 服务状态

  • 检查 CoreDNS Pod 状态 使用 kubectl get pods -n kube-system -l k8s-app=kube-dns 查看 CoreDNS Pod 的运行状态,确保其正常运行。

    > kubectl get pods -n kube-system -l k8s-app=kube-dns
    NAME                       READY   STATUS    RESTARTS   AGE
    coredns-549dfbdc5c-96ccs   1/1     Running   0          34d
    coredns-549dfbdc5c-dk47s   1/1     Running   0          34d
    coredns-549dfbdc5c-jmvjw   1/1     Running   0          34d
    coredns-549dfbdc5c-kmr95   1/1     Running   0          34d
    coredns-549dfbdc5c-zb8tz   1/1     Running   0          34d
    
  • 查看 CoreDNS 配置 使用 kubectl -n kube-system describe configmap coredns 查看 CoreDNS 的配置文件,确认配置无误。

3.2 验证 Kubernetes 集群 DNS 解析

  • 使用 nslookup 或 dig 命令测试解析 在问题 Pod 中运行 nslookup <hostname> 或 dig <hostname>,验证 DNS 解析是否正确。

    > kubectl exec -it td-ba-coding-react-front-devops-guide-prod-f54f5968f-wsnc5 -n prod -- nslookup td-ba-coding-devops-guide-prod.prod.svc.cluster.local
    Server:         172.16.29.150
    Address:        172.16.29.150#53
    
    Name:   td-ba-coding-devops-guide-prod.prod.svc.cluster.local
    Address: 172.16.38.234
    

    nslookup 成功解析表明 Kubernetes 的 DNS 系统正常工作,但 Nginx 由于缺乏 resolver 指令,无法利用这套 DNS 系统进行解析。

  • 测试不同命名空间的解析 验证其他命名空间中的 DNS 解析是否正常,以排除命名空间特定问题。

3.3 合理的猜测

​ Nginx 默认在启动时解析配置文件中的域名并将其缓存。如果配置文件中的域名(如 td-ba-coding-devops-guide-prod.prod.svc.cluster.local)在 Nginx 启动后发生变化,或者在运行时才需要解析,Nginx 将无法动态解析这些域名。resolver 指令用于告诉 Nginx 在请求期间如何解析 DNS,这在处理动态或变化的 DNS 解析时非常重要。

​ 当 Nginx 处理请求时,如果没有配置 resolver 指令,它会无法解析 hostname,从而产生 no resolver defined to resolve 的错误。这意味着 Nginx试图解析一个未缓存或需要动态解析的域名,但没有指定用于解析的 DNS 服务器。

4. 解决方案

在 Nginx 配置中添加 resolver 指令,指向 Kubernetes 集群的 DNS 服务器。例如:

如:

resolver kube-dns.kube-system.svc.cluster.local valid=30s;

或者直接使用 IP 地址:

resolver 172.16.29.150 valid=30s;

这将告诉 Nginx 使用指定的 DNS 服务器来解析 hostname,并且每隔 30 秒重新验证(更新)解析结果。

完整配置示例:

server {
    listen 80;
    server_name _;
    index index.jsp index.html index.htm index.php default.html default.htm default.php;
    root  /usr/share/nginx/html/;
    resolver kube-dns.kube-system.svc.cluster.local valid=30s;

    client_max_body_size 500m;
    proxy_buffering    on;
    proxy_buffer_size  4k;
    proxy_buffers 4  8k;
    proxy_busy_buffers_size 12k;

    access_log /dev/stdout main;
    error_log /dev/stderr info;

    location / {
		try_files $uri $uri/ /index.html;
	}

    location /backend/ {
        proxy_next_upstream error timeout http_500 http_502 http_503 http_504 http_404;

        proxy_read_timeout 60s;
        proxy_set_header Connection "";
        proxy_connect_timeout 60;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_pass http://td-ba-coding-devops-guide-prod.prod.svc.cluster.local:80/hello?$query_string;
	}

}
# nginx # 云原生 # docker # k8s
服务治理三板斧之降级
  • 文章目录
  • 站点概览
lw‘Blogs

lw‘Blogs

自信人生二百年,会当水击三千里

80 日志
8 分类
40 标签
RSS
Github E-mail
Creative Commons
© 2025 京ICP备2022025426号-1