首页 > 解决方案 > nginx 入口:在 nginx-controller 日志中忽略 yaml 定义中的冲突主机,但创建非工作情况

问题描述

安装:https ://helm.nginx.com/稳定版

[root@node1 ~]# helm search repo nginx-stable 
NAME                        CHART VERSION   APP VERSION DESCRIPTION             
nginx-stable/nginx-ingress  0.6.1           1.8.1       NGINX Ingress Controller

kubectl run nginx --image=nginx 
kubectl run apache --image=httpd 
kubectl expose pod nginx --port=80 --name=nginx-svc
kubectl expose pod apache --port=80

作为测试两个 pod 的方法,nodeport 可以成功访问

我创建了两个 yaml 文件来让入口工作

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ing-rule
  annotations:
    nginx.org/rewrites: "serviceName=nginx-svc rewrite=/"
spec:
  rules:
  - host: kubernetes.somelan.lan
    http:
      paths:
      - path: /nginx
        backend:
          serviceName: nginx-svc
          servicePort: 80

对于阿帕奇

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: apache-ingress
  annotations:
    nginx.org/rewrites: "serviceName=apache rewrite=/"
spec:
  rules:
  - host: kubernetes.somelan.lan
    http:
      paths:
      - path: /apache
        backend:
          serviceName: apache
          servicePort: 80

当我分别应用这两个 yaml 时,它们被 nginx-controller 接受,无论它记录

conflicting server name "kubernetes.somelan.lan" on 0.0.0.0:80, ignored

结果: 我可以成功访问http://kubernetes.somelan.lan/apache,但是我无法访问http://kubernetes.somelan.lan/nginx。以不同的顺序应用 yaml 会呈现相同的结果如果我删除 apache yaml,则 nginx 入口开始工作;我可以访问http://kubernetes.somelan.lan/nginx

错误代码和日志是:

020/10/27 20:34:28 [error] 62#62: *20 open() "/etc/nginx/html/nginx" failed (2: No such file or directory), client: 10.10.70.22, server: kubernetes.somelan.lan, request: "GET /nginx HTTP/1.1", host: "kubernetes.somelan.lan"
10.10.70.22 - - [27/Oct/2020:20:34:28 +0000] "GET /nginx HTTP/1.1" 404 153 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0" "-"
2020/10/27 20:34:28 [error] 62#62: *20 open() "/etc/nginx/html/favicon.ico" failed (2: No such file or directory), client: 10.10.70.22, server: kubernetes.somelan.lan, request: "GET /favicon.ico HTTP/1.1", host: "kubernetes.somelan.lan", referrer: "kubernetes.somelan.lan/nginx"
10.10.70.22 - - [27/Oct/2020:20:34:28 +0000] "GET /favicon.ico HTTP/1.1" 404 153 "kubernetes.somelan.lan/nginx" "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:82.0) Gecko/20100101 Firefox/82.0" "-"

但是,如果我创建一个 yaml:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: nginx-ing-rule
  annotations:
    nginx.org/rewrites: "serviceName=nginx-svc rewrite=/; serviceName=apache rewrite=/"
spec:
  rules:
  - host: kubernetes.somelan.lan
    http:
      paths:
      - path: /nginx
        backend:
          serviceName: nginx-svc
          servicePort: 80
      - path: /apache
        backend:
          serviceName: apache
          servicePort: 80

一切都按预期工作,我可以访问 /nginx 和 /apache

在 nginx 控制器上,使用单个 yaml 会在控制器上提供以下配置:

# configuration for default/nginx-ing-rule
  
upstream default-nginx-ing-rule-kubernetes.somelan.lan-apache-80 {
    zone default-nginx-ing-rule-kubernetes.somelan.lan-apache-80 256k;
    random two least_conn;
    server 10.233.112.2:80 max_fails=1 fail_timeout=10s max_conns=0;
}
upstream default-nginx-ing-rule-kubernetes.somelan.lan-nginx-svc-80 {
    zone default-nginx-ing-rule-kubernetes.somelan.lan-nginx-svc-80 256k;
    random two least_conn;
    server 10.233.64.2:80 max_fails=1 fail_timeout=10s max_conns=0;
}
server {
    listen 80;
    server_tokens on;
    server_name kubernetes.somelan.lan;
    location /nginx {
        proxy_http_version 1.1;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
        client_max_body_size 1m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering on;

        proxy_pass http://default-nginx-ing-rule-kubernetes.somelan.lan-nginx-svc-80/       
        
    }
    location /apache {
        proxy_http_version 1.1;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
        client_max_body_size 1m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering on;

        proxy_pass http://default-nginx-ing-rule-kubernetes.somelan.lan-apache-80/;         
    }
    

如果我应用我之前指定的 2 个 yaml,nginx 控制器有 2 个配置

Apache入口的配置

# configuration for default/apache-ingress

upstream default-apache-ingress-kubernetes.somelan.lan-apache-80 {
    zone default-apache-ingress-kubernetes.somelan.lan-apache-80 256k;
    random two least_conn;
    
    server 10.233.112.2:80 max_fails=1 fail_timeout=10s max_conns=0;    
}

server {    
    listen 80;
    server_tokens on;
    server_name kubernetes.somelan.lan;
    location /apache {
        proxy_http_version 1.1;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
        client_max_body_size 1m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering on;
        
        proxy_pass http://default-apache-ingress-kubernetes.somelan.lan-apache-80/;
    }
}

    }

nginx入口的配置

# configuration for default/nginx-ing-rule

upstream default-nginx-ing-rule-kubernetes.somelan.lan-nginx-svc-80 {
    zone default-nginx-ing-rule-kubernetes.somelan.lan-nginx-svc-80 256k;
    random two least_conn;
    
    server 10.233.64.2:80 max_fails=1 fail_timeout=10s max_conns=0;
    
}


server {
    listen 80;
    server_tokens on;
    server_name kubernetes.somelan.lan;
    location /nginx {
        proxy_http_version 1.1;
        proxy_connect_timeout 60s;
        proxy_read_timeout 60s;
        proxy_send_timeout 60s;
        client_max_body_size 1m;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Host $host;
        proxy_set_header X-Forwarded-Port $server_port;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffering on;
        
        proxy_pass http://default-nginx-ing-rule-kubernetes.somelan.lan-nginx-svc-80/;
        
    }   
}

我期望使用两个 yaml 的方法应该呈现与使用一个 yaml 文件相同的结果,我错了吗?

标签: nginxkubernetesnginx-ingressmetallb

解决方案


这里几乎没有什么需要解释的。

  1. 您看到的错误:

conflicting server name "kubernetes.somelan.lan" on 0.0.0.0:80, ignored

是因为你不能有两个相同的服务器块并在同server_name一个端口上侦听。

  1. 了解nginx 模型中的操作是如何工作的很重要。这些如下:
  • 按字段排序 Ingress 规则CreationTimestamp,即旧规则优先。

  • 如果同一主机的相同路径在多个 Ingress 中定义,则最旧的规则获胜。

  • 如果多个 Ingress 包含同一主机的 TLS 部分,则最旧的规则获胜。

  • 如果多个 Ingress 定义了影响 Server 块配置的注释,则最旧的规则获胜。

  • 创建 NGINX 服务器列表(每个主机名)

  • 创建 NGINX 上游列表

  • 如果多个 Ingress 为同一主机定义了不同的路径,则入口控制器将合并定义。

  • 注释应用于 Ingress 中的所有路径。

  • 多个 Ingress 可以定义不同的注解。这些定义不在 Ingress 之间共享。

  1. 另外,请记住当需要重新加载时
  • 新入口资源已创建。

  • TLS 部分已添加到现有 Ingress。

  • Ingress 注释的变化不仅仅影响上游配置。例如负载平衡注释不需要重新加载。

  • 从 Ingress 添加/删除路径。

  • 一个 Ingress、Service、Secret 被移除。

  • Ingress 中一些缺失的引用对象是可用的,例如 Service 或 Secret。

  • 更新了一个秘密。

  1. 现在,根据上面的信息,在您的用例中,如果您创建了两个单独的 Ingress,则应该发生以下场景:

如果多个 Ingress 为同一主机定义了不同的路径,则入口控制器将合并定义。

如果这还没有发生,您需要检查您的 Ingress Controller 及其版本,以确保它支持合并操作。您可以在此处查看更多详细信息。

  1. 最后回答你的主要问题:

我期望使用两个 yaml 的方法应该呈现与使用一个 yaml 文件相同的结果,我错了吗?

这取决于您的配置和您使用的 Ingress Controller。server_name在您的特定用例中,由于冲突,使用两个 yaml 与使用单个 yaml 的工作方式不同。您发现很难启用合并选项,请考虑使用Merge Ingress Controller

Merge Ingress Controller 将多个入口资源组合成一个新资源。


推荐阅读