Kubernetes несколько входных объектов с одинаковыми конфигами - PullRequest
1 голос
/ 03 марта 2020

Предположим, я создаю несколько входных объектов в k8s, которые указывают на один и тот же сервис, один и тот же путь и абсолютно одинаковы, только они имеют разные имена, например, -. ingress-1 и ingress-2 . Как обрабатываются запросы в этом случае? Дублированы ли запросы или входящий обрабатывает запрос?

PS; - я знаю, что в этом нет особого смысла, но я что-то проверяю.

Ответы [ 3 ]

2 голосов
/ 03 марта 2020

Давайте проверим, как это работает!

У меня по умолчанию nginx развертывание

# kubectl -n test get pods -o wide | grep nginx
nginx-65f88748fd-6w6fj           1/1     Running   0          26h     10.8.253.25    k8s-vm02   <none>           <none>
nginx-65f88748fd-8fp7p           1/1     Running   0          26h     10.8.252.205   k8s-vm01   <none>           <none>
nginx-65f88748fd-c7j29           1/1     Running   0          26h     10.8.253.24    k8s-vm02   <none>           <none>
nginx-65f88748fd-frsbq           1/1     Running   0          26h     10.8.252.201   k8s-vm01   <none>           <none>
nginx-65f88748fd-p4zvm           1/1     Running   0          26h     10.8.252.204   k8s-vm01   <none>           <none>
nginx-65f88748fd-pd8gv           1/1     Running   0          25h     10.8.253.27    k8s-vm02   <none>           <none>
nginx-65f88748fd-rkcjl           1/1     Running   0          26h     10.8.252.206   k8s-vm01   <none>           <none>
nginx-65f88748fd-rn49k           1/1     Running   0          26h     10.8.253.26    k8s-vm02   <none>           <none>
nginx-65f88748fd-w9dz8           1/1     Running   0          26h     10.8.252.203   k8s-vm01   <none>           <none>
nginx-65f88748fd-xh42v           1/1     Running   0          25h     10.8.253.28    k8s-vm02   <none>           <none>

service

# kubectl -n test get svc
NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
nginx   ClusterIP   10.8.254.218   <none>        80/TCP    12d

и 2 аналогичных ресурса Ingress в одном и том же пространстве имен

# kubectl -n test get ing
NAME             HOSTS            ADDRESS   PORTS   AGE
test-ingress-1   nginx.test.com             80      20m
test-ingress-2   nginx.test.com             80      20m

Их YAML:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: test
  name: test-ingress-1
  annotations:
    kubernetes.io/ingress.class: "service"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: nginx
          servicePort: 80

и

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: test
  name: test-ingress-2
  annotations:
    kubernetes.io/ingress.class: "service"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: nginx
          servicePort: 80

еще одна вещь о ingress.class: "service" - в моей среде более 1 входного контроллера, и этот конкретный входной контроллер

nginx-ingress-service-6gkhh                1/1     Running   0          4m20s   10.8.255.243   k8s-vm02   <none>           <none>

был создан специально для демонстрации этого примера, поэтому не обращайте на него внимания

В любом случае, ресурс Ingress nginx.test.com/foo работает сейчас?

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Да, это так. Что под капотом? Конфигурация Nginx внутри ingress-контроллера имеет только один server_name nginx.test.com независимо от того, сколько у нас аналогичных ресурсов Ingress

# kubectl -n kube-system exec nginx-ingress-service-6gkhh -- cat /etc/nginx/nginx.conf
...
## start server nginx.test.com
    server {
        server_name nginx.test.com ;

        listen 80;

        listen [::]:80;

        set $proxy_upstream_name "-";

        location ~* ^/foo\/?(?<baseuri>.*) {
...
            proxy_pass http://test-nginx-80;
...
    ## end server nginx.test.com

upstreams:

    upstream test-nginx-80 {

        keepalive 32;

        server 10.8.252.203:80 max_fails=0 fail_timeout=0;
        server 10.8.253.26:80 max_fails=0 fail_timeout=0;
        server 10.8.252.201:80 max_fails=0 fail_timeout=0;
        server 10.8.253.25:80 max_fails=0 fail_timeout=0;
        server 10.8.252.204:80 max_fails=0 fail_timeout=0;
        server 10.8.253.24:80 max_fails=0 fail_timeout=0;
        server 10.8.252.205:80 max_fails=0 fail_timeout=0;
        server 10.8.252.206:80 max_fails=0 fail_timeout=0;
        server 10.8.253.27:80 max_fails=0 fail_timeout=0;
        server 10.8.253.28:80 max_fails=0 fail_timeout=0;

    }

Давайте удалим test-ingress-1 Ingress ресурс

# kubectl -n test delete ing test-ingress-1
ingress.extensions "test-ingress-1" deleted

Ingress все еще работает:

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    body {
        width: 35em;
        margin: 0 auto;
        font-family: Tahoma, Verdana, Arial, sans-serif;
    }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Таким образом, вы можете создать столько ресурсов Ingress, сколько захотите (В случае использования nginx -ingress-controller)

UPD: Давайте создадим еще одно развертывание в том же пространстве имен:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: apache
  namespace: test
spec:
  replicas: 3
  selector:
    matchLabels:
      app: apache
  template:
    metadata:
      labels:
        app: apache
    spec:
      containers:
      - name: frontend
        image: httpd
        ports:
        - containerPort: 80

и еще один сервис

apiVersion: v1
kind: Service
metadata:
  name: apache
  namespace: test
spec:
  ports:
  - name: 80-80
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: apache
  type: ClusterIP

Далее давайте изменим Ingress ресурс test-ingress-2:

apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  namespace: test
  name: test-ingress-2
  annotations:
    kubernetes.io/ingress.class: "service"
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
  - host: nginx.test.com
    http:
      paths:
      - path: /foo
        backend:
          serviceName: apache # <-------
          servicePort: 80

Наконец, пространство имен test включает в себя этот список ресурсов:

# kubectl -n test get all
NAME                                 READY   STATUS    RESTARTS   AGE
pod/apache-cfdf8d79c-2m666           1/1     Running   0          13m
pod/apache-cfdf8d79c-d995s           1/1     Running   0          13m
pod/apache-cfdf8d79c-tq8d7           1/1     Running   0          13m
pod/nginx-65f88748fd-6w6fj           1/1     Running   0          45h
pod/nginx-65f88748fd-8fp7p           1/1     Running   0          45h
pod/nginx-65f88748fd-c7j29           1/1     Running   0          45h
pod/nginx-65f88748fd-frsbq           1/1     Running   0          46h
pod/nginx-65f88748fd-p4zvm           1/1     Running   0          45h
pod/nginx-65f88748fd-pd8gv           1/1     Running   0          45h
pod/nginx-65f88748fd-rkcjl           1/1     Running   0          45h
pod/nginx-65f88748fd-rn49k           1/1     Running   0          45h
pod/nginx-65f88748fd-w9dz8           1/1     Running   0          45h
pod/nginx-65f88748fd-xh42v           1/1     Running   0          45h

NAME             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/apache   ClusterIP   10.8.254.47    <none>        80/TCP    12m
service/nginx    ClusterIP   10.8.254.218   <none>        80/TCP    12d

# kubectl -n test get ing
NAME             HOSTS            ADDRESS   PORTS   AGE
test-ingress-1   nginx.test.com             80      9m15s
test-ingress-2   nginx.test.com             80      54s

контроллер ingreess nginx.conf показывает два списка восходящих потоков

    upstream test-apache-80 {

        keepalive 32;

        server 10.8.253.31:80 max_fails=0 fail_timeout=0;
        server 10.8.252.208:80 max_fails=0 fail_timeout=0;
        server 10.8.253.32:80 max_fails=0 fail_timeout=0;

    }

    upstream test-nginx-80 {

        keepalive 32;

        server 10.8.252.204:80 max_fails=0 fail_timeout=0;
        server 10.8.252.205:80 max_fails=0 fail_timeout=0;
        server 10.8.253.27:80 max_fails=0 fail_timeout=0;
        server 10.8.253.25:80 max_fails=0 fail_timeout=0;
        server 10.8.253.24:80 max_fails=0 fail_timeout=0;
        server 10.8.252.206:80 max_fails=0 fail_timeout=0;
        server 10.8.253.26:80 max_fails=0 fail_timeout=0;
        server 10.8.252.203:80 max_fails=0 fail_timeout=0;
        server 10.8.253.28:80 max_fails=0 fail_timeout=0;
        server 10.8.252.201:80 max_fails=0 fail_timeout=0;

    }

, но он передает запросы только одному из них

    ## start server nginx.test.com
    server {
        server_name nginx.test.com ;

        listen 80;

        listen [::]:80;

        set $proxy_upstream_name "-";

        location ~* ^/foo\/?(?<baseuri>.*) {

            set $namespace      "test";
            set $ingress_name   "test-ingress-1"; <------
            set $service_name   "nginx";
            set $service_port   "80";
            set $location_path  "/foo";

...

            rewrite /foo/(.*) /$1 break;
            rewrite /foo / break;
            proxy_pass http://test-nginx-80;  <-------

            proxy_redirect                          off;
# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...

Каждый из входящих ресурсов появляется там в соответствии со временем создания. Удаление ресурса Ingress

ingress.networking.k8s.io "test-ingress-1" deleted

делает трафик прокси-сервера ingress-контроллера c to Apache восходящими

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<html><body><h1>It works!</h1></body></html>

, чтобы было ясно, что мы можем воссоздать ресурсы Ingress в обратном порядке:

# kubectl -n test delete ing test-ingress-1 test-ingress-2
ingress.extensions "test-ingress-1" deleted
ingress.extensions "test-ingress-2" deleted

# kubectl -n test create -f /tmp/ing2.yaml
ingress.networking.k8s.io/test-ingress-2 created # Apache
# kubectl -n test create -f /tmp/ing1.yaml
ingress.networking.k8s.io/test-ingress-1 created # Nginx

# curl -H "Host: nginx.test.com" http://10.8.255.243:80/foo
<html><body><h1>It works!</h1></body></html> # Apache

Еще одно замечание: Есть несколько случаев перезагрузки конфигурации ingress-controller, я имею в виду, когда он перезагружает config и как он фактически перезагружает config? Но это совершенно другой вопрос ...

1 голос
/ 03 марта 2020

Входные контроллеры (будь то nginx или haproxy или любой другой контроллер) работают более или менее одинаково. Если объект Ingress создан или изменен, они прослушивают это и для каждого хоста / пути во входе они создают правило, согласно которому, если запрос достигает контроллера Ingress с этим конкретным хостом / путем, он должен пересылать трафик c к службе, настроенной для этого пути.

Итак, в вашем примере вы говорите, что добавляете несколько объектов Ingress, имеющих одинаковые конфигурации хоста / пути, указывающие на одну и ту же службу. Я думаю, что это до реализации контроллера Ingress; как они хотят обрабатывать дубликаты Ingress. Не имеет смысла добавлять дубликаты правил для одного и того же имени хоста (не имеет значения, указывает ли оно на одну и ту же службу или другую службу, но в случае другой вспомогательной службы это большая проблема / неоднозначность).

Но я бы предположил, что даже если контроллер Ingress разрешает подобные конфигурации и программирует несколько правил для одного хоста / пути, он не будет выполнять мультиплексирование. Возможно, оно будет соответствовать первому правилу и переадресовано на службу, стоящую за ним.

Как он определяет, к какой службе направить? Он основан на том, по какому имени хоста трафик c достиг контроллера Ingress.

Вы можете легко проверить поведение. Exe c в контроллер и посмотреть его файл conf. Для входного контроллера nginx файл conf будет находиться в /etc/nginx/nginx.conf, который будет определять правила и действия.

1 голос
/ 03 марта 2020

Если вы имеете в виду объекты Ingress с одним и тем же контроллером: как правило, ничего интересного, большинство избыточных маршрутов с дублированием.

Если вы имеете в виду два контроллера, каждый из которых указывает на отдельный (но идентичный) вход: оба контроллера настроить себя с запрошенными маршрутами. Они абсолютно независимы и ничего не знают друг о друге.

...