ingress nginx: переписать логику правил и поиск местоположения - PullRequest
0 голосов
/ 01 октября 2019

Я развернул в своем кластере k8s входной контроллер nginx для доступа к внутреннему приложению.

При тестировании конфигурации входных ресурсов я заметил, что если я добавлю правило перезаписи, мне также потребуется объявить путь дляпереписанный URI, указывающий на ту же службу.

Например, следующий входной конфиг не работает:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: fieldprov-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /wetty
    nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    kubernetes.io/ingress.class: "field-management"
spec:
  tls:
  - hosts:
    - ccfanhe09.sce-lab.com
  rules:
    - host: ccfanhe09.sce-lab.com
      http:
        paths:
         - path: /provisioning
           backend:
            serviceName: fieldprov-app
            servicePort: 3000

Контроллер перенаправит меня на свой внутренний сервер по умолчанию, связанный с "/"

fd10::2:102 - [fd10::2:102] - - [01/Oct/2019:19:34:07 +0000] "GET /provisioning HTTP/2.0" 304 0 "-" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0" 236 0.003 [default-fieldprov-app-3000] [] [fd10::1:10a]:
3000 0 0.003 304 64895f25fd3fb9937f66ebbcee369c81
fd10::2:102 - [fd10::2:102] - - [01/Oct/2019:19:34:07 +0000] "GET /wetty/socket.io/socket.io.js HTTP/2.0" 404 159 "https://ccfanhe10.sce-lab.com:30000/provisioning" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firef
ox/60.0" 71 0.002 [upstream-default-backend] [] 127.0.0.1:8181 159 0.003 404 8310972dd6b39f294bae7550305bd7c2
fd10::2:102 - [fd10::2:102] - - [01/Oct/2019:19:34:07 +0000] "GET /wetty/wetty.min.js HTTP/2.0" 404 159 "https://ccfanhe10.sce-lab.com:30000/provisioning" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0" 2
4 0.001 [upstream-default-backend] [] 127.0.0.1:8181 159 0.002 404 47875d655cf4bcd02fc6212dc6142848
fd10::2:102 - [fd10::2:102] - - [01/Oct/2019:19:34:07 +0000] "GET /wetty/wetty.min.js HTTP/2.0" 404 159 "https://ccfanhe10.sce-lab.com:30000/provisioning" "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:60.0) Gecko/20100101 Firefox/60.0" 2
4 0.001 [upstream-default-backend] [] 127.0.0.1:8181 159 0.000 404 08d1fd4cc72a5475d0fcfb4ca6a4cb2b``

Так что мне кажется, что контроллер выполняет 2-й поиск после применения правила перезаписи.

Ниже приведен мой nginx.conf, связанный с конфигурацией входа, описанной выше:

## start server ccfanhe10.sce-lab.com
    server {
        server_name ccfanhe10.sce-lab.com ;

        listen 80  ;
        listen [::]:80  ;
        listen 443  ssl http2 ;
        listen [::]:443  ssl http2 ;

        set $proxy_upstream_name "-";

        # PEM sha: 692b563bafa154b7d28350ef01e7c4d53ec2afd1
        ssl_certificate                         /etc/ingress-controller/ssl/default-fake-certificate.pem;
        ssl_certificate_key                     /etc/ingress-controller/ssl/default-fake-certificate.pem;

        ssl_certificate_by_lua_block {
            certificate.call()
        }

        location ~* "^/provisioning" {

            set $namespace      "default";
            set $ingress_name   "fieldprov-app";
            set $service_name   "fieldprov-app";
        set $service_port   "{0 3000 }";
            set $location_path  "/provisioning";

            rewrite_by_lua_block {
                lua_ingress.rewrite({
                    force_ssl_redirect = true,
                    use_port_in_redirects = false,
                })
                balancer.rewrite()
                plugins.run()
            }

            header_filter_by_lua_block {

                plugins.run()
            }
            body_filter_by_lua_block {

            }

            log_by_lua_block {

                balancer.log()

                monitor.call()

                plugins.run()
            }

            if ($scheme = https) {
                more_set_headers                        "Strict-Transport-Security: max-age=15724800; includeSubDomains";
            }

            rewrite_log on;

            port_in_redirect off;

            set $balancer_ewma_score -1;
            set $proxy_upstream_name    "default-fieldprov-app-3000";
            set $proxy_host             $proxy_upstream_name;
            set $pass_access_scheme $scheme;
            set $pass_server_port $server_port;
            set $best_http_host $http_host;
            set $pass_port $pass_server_port;

            set $proxy_alternative_upstream_name "";

            client_max_body_size                    1m;

            proxy_set_header Host                   $best_http_host;

            # Pass the extracted client certificate to the backend

            # Allow websocket connections
            proxy_set_header                        Upgrade           $http_upgrade;

            proxy_set_header                        Connection        $connection_upgrade;

            proxy_set_header X-Request-ID           $req_id;
            proxy_set_header X-Real-IP              $the_real_ip;

            proxy_set_header X-Forwarded-For        $the_real_ip;

            proxy_set_header X-Forwarded-Host       $best_http_host;
            proxy_set_header X-Forwarded-Port       $pass_port;
            proxy_set_header X-Forwarded-Proto      $pass_access_scheme;

            proxy_set_header X-Original-URI         $request_uri;

            proxy_set_header X-Scheme               $pass_access_scheme;

            # Pass the original X-Forwarded-For
            proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;

            # mitigate HTTPoxy Vulnerability
            # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
            proxy_set_header Proxy                  "";

            # Custom headers to proxied server

            proxy_connect_timeout                   5s;
            proxy_send_timeout                      60s;
            proxy_read_timeout                      60s;

            proxy_buffering                         off;
            proxy_buffer_size                       4k;
            proxy_buffers                           4 4k;
            proxy_request_buffering                 on;
            proxy_http_version                      1.1;

            proxy_cookie_domain                     off;
            proxy_cookie_path                       off;

            # In case of errors try the next upstream server before returning an error
            proxy_next_upstream                     error timeout;
            proxy_next_upstream_timeout             0;
            proxy_next_upstream_tries               3;

            rewrite "(?i)/provisioning" /wetty break;
            proxy_pass http://upstream_balancer;

            proxy_redirect                          off;

        }

        location ~* "^/" {

            set $namespace      "";
            set $ingress_name   "";
            set $service_name   "";
        set $service_port   "{0 0 }";
            set $location_path  "/";

            rewrite_by_lua_block {
                lua_ingress.rewrite({
                    force_ssl_redirect = true,
                    use_port_in_redirects = false,
                })
                balancer.rewrite()
                plugins.run()
            }

            header_filter_by_lua_block {

                plugins.run()
            }
            body_filter_by_lua_block {

            }

            log_by_lua_block {

                balancer.log()

                monitor.call()

                plugins.run()
            }

            if ($scheme = https) {
                more_set_headers                        "Strict-Transport-Security: max-age=15724800; includeSubDomains";
            }

            rewrite_log on;

            port_in_redirect off;

            set $balancer_ewma_score -1;
            set $proxy_upstream_name    "upstream-default-backend";
            set $proxy_host             $proxy_upstream_name;
            set $pass_access_scheme $scheme;
            set $pass_server_port $server_port;
            set $best_http_host $http_host;
            set $pass_port $pass_server_port;

            set $proxy_alternative_upstream_name "";

            client_max_body_size                    1m;

            proxy_set_header Host                   $best_http_host;

            # Pass the extracted client certificate to the backend

            # Allow websocket connections
            proxy_set_header                        Upgrade           $http_upgrade;

            proxy_set_header                        Connection        $connection_upgrade;

            proxy_set_header X-Request-ID           $req_id;
            proxy_set_header X-Real-IP              $the_real_ip;

            proxy_set_header X-Forwarded-For        $the_real_ip;

            proxy_set_header X-Forwarded-Host       $best_http_host;
            proxy_set_header X-Forwarded-Port       $pass_port;
            proxy_set_header X-Forwarded-Proto      $pass_access_scheme;

            proxy_set_header X-Original-URI         $request_uri;

            proxy_set_header X-Scheme               $pass_access_scheme;

            # Pass the original X-Forwarded-For
            proxy_set_header X-Original-Forwarded-For $http_x_forwarded_for;

            # mitigate HTTPoxy Vulnerability
            # https://www.nginx.com/blog/mitigating-the-httpoxy-vulnerability-with-nginx/
            proxy_set_header Proxy                  "";

            # Custom headers to proxied server

            proxy_connect_timeout                   5s;
            proxy_send_timeout                      60s;
            proxy_read_timeout                      60s;

            proxy_buffering                         off;
            proxy_buffer_size                       4k;
            proxy_buffers                           4 4k;
            proxy_request_buffering                 on;
            proxy_http_version                      1.1;

            proxy_cookie_domain                     off;
            proxy_cookie_path                       off;

            # In case of errors try the next upstream server before returning an error
            proxy_next_upstream                     error timeout;
            proxy_next_upstream_timeout             0;
            proxy_next_upstream_tries               3;

            rewrite "(?i)/" /wetty break;
            proxy_pass http://upstream_balancer;

            proxy_redirect                          off;

        }

    }
    ## end server ccfanhe10.sce-lab.com

Я не понимаю правила перезаписи в расположении "^ /". Также я подумал, что добавление ключевого слова break к правилу перезаписи позволит избежать дополнительного поиска URI, но это не то поведение, которое я вижу. Если я не создаю местоположение для «/ wetty», которое указывает на тот же сервис, что и «/ provisioning», оно не работает.

Я ищу объяснение ожидаемого поведения в таких случаях. состояние.

Спасибо за вашу поддержку !!

1 Ответ

0 голосов
/ 07 октября 2019

Попробуйте использовать группы захвата, как описано в здесь или здесь разделе документации ingres-nginx.

Начиная с версии 0.22.0, ingressопределения, использующие аннотацию nginx.ingress.kubernetes.io/rewrite-target, не имеют обратной совместимости с предыдущими версиями. В версии 0.22.0 и более поздних версиях любые подстроки в URI запроса, которые необходимо передать переписанному пути, должны быть явно определены в группе захвата .

Захваченные группы сохраняются в пронумерованных заполнителях в хронологическом порядке в форме $1, $2 ... $n. Эти заполнители можно использовать в качестве параметров в аннотации rewrite-target.

Таким образом, ваш входной конфиг должен выглядеть примерно так:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: fieldprov-app
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /wetty/$2
    nginx.ingress.kubernetes.io/enable-rewrite-log: "true"
    kubernetes.io/ingress.class: "field-management"
spec:
  tls:
  - hosts:
    - ccfanhe09.sce-lab.com
  rules:
    - host: ccfanhe09.sce-lab.com
      http:
        paths:
         - path: /provisioning/(/|$)(.*)
           backend:
            serviceName: fieldprov-app
            servicePort: 3000

Что касается nginx.conf, то он выглядиттак как его настройки вводятся из nginx-контроллера с помощью lua-nginx-module, вы можете прочитать об этом здесь .


Обновление:

Если правило перезаписи работает правильно, никаких дополнительных поисков не должно быть. Я не смог найти ничего подобного в nginx ingress аннотации .

Вы можете проверить, работает ли правило перезаписи, используя команду curl -I -k <URI>:

$ curl -I -k http://approot.bar.com/
HTTP/1.1 302 Moved Temporarily
Server: nginx/1.11.10
Date: Mon, 13 Mar 2017 14:57:15 GMT
Content-Type: text/html
Content-Length: 162
Location: http://stickyingress.example.com/app1
Connection: keep-alive
...