Kubernetes - Как получить доступ к балансировке нагрузки nginx из-за пределов кластера с помощью службы NodePort - PullRequest
0 голосов
/ 17 мая 2018

У меня есть кластер Kubernetes с главным узлом и двумя другими узлами:

sudo kubectl get nodes
NAME                STATUS    ROLES     AGE       VERSION
kubernetes-master   Ready     master    4h        v1.10.2
kubernetes-node1    Ready     <none>    4h        v1.10.2
kubernetes-node2    Ready     <none>    34m       v1.10.2

Каждый из них работает на виртуальной машине VirtualBox Ubuntu, доступной с гостевого компьютера:

kubernetes-master (192.168.56.3)
kubernetes-node1  (192.168.56.4)
kubernetes-node2 (192.168.56.6)

Я развернул сервер nginx с двумя репликами, по одному модулю на kubernetes-node-x:

sudo kubectl get pods -o wide
NAME                                READY     STATUS    RESTARTS   AGE       IP               NODE
nginx-deployment-64ff85b579-5k5zh   1/1       Running   0          8s        192.168.129.71   kubernetes-node1
nginx-deployment-64ff85b579-b9zcz   1/1       Running   0          8s        192.168.22.66    kubernetes-node2

Далее я предоставляю сервис для развертывания nginx как NodePort для доступа к нему вне кластера:

sudo kubectl expose deployment/nginx-deployment --type=NodePort

sudo kubectl get services 
NAME               TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
kubernetes         ClusterIP   10.96.0.1      <none>        443/TCP        4h
nginx-deployment   NodePort    10.96.194.15   <none>        80:32446/TCP   2m

sudo kubectl describe service nginx-deployment
Name:                     nginx-deployment
Namespace:                default
Labels:                   app=nginx
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP:                       10.96.194.15
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  32446/TCP
Endpoints:                192.168.129.72:80,192.168.22.67:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Я могу получить доступ к каждому модулю в узле напрямую, используя их IP-адрес узла

kubernetes-node1 http://192.168.56.4:32446/
kubernetes-node2 http://192.168.56.6:32446/

Но я думал, что K8s предоставил какой-то внешний кластерный ip, который уравновешивал запросы к узлам извне. Что это за IP ??

1 Ответ

0 голосов
/ 17 мая 2018

Но я подумал, что K8s предоставил какой-то внешний кластерный ip, который уравновешивал запросы к узлам извне. Что это за IP ??

  • IP-адрес кластера является внутренним для кластера. Не подвергается воздействию извне, оно предназначено для взаимодействия через кластер.

  • Действительно, у вас есть тип сервиса LoadBanacer, который может выполнить такой трюк, который вам нужен, только он зависит от того, работают ли облачные провайдеры или границы мини-куба / докера.

Я могу получить доступ к каждому модулю в узле напрямую, используя их IP-адрес узла

  • На самом деле вы не получаете к ним индивидуальный доступ таким образом. NodePort делает немного другой трюк, так как это по существу запросы балансировки нагрузки извне на ЛЮБОМ выставленном IP-адресе узла. Короче говоря, если вы нажмете на любой из IP-адресов узла с помощью открытого NodePort, kube-proxy убедится, что требуемая служба его получит, а затем служба будет выполнять циклический перебор через активные модули, поэтому, хотя вы попадаете на конкретный IP-адрес узла, вы не обязательно получить модуль, работающий на этом конкретном узле. Более подробную информацию об этом вы можете найти здесь: https://medium.com/google-cloud/kubernetes-nodeport-vs-loadbalancer-vs-ingress-when-should-i-use-what-922f010849e0,, как сказал автор, не технически наиболее точное представление, но попытка показать на логическом уровне, что происходит с экспозицией NodePort:

NodePort Illustration

  • В качестве sidenote, чтобы сделать это на голом металле и сделать ssl или что-то подобное, вам необходимо обеспечить вход самостоятельно. Скажем, поместите один nginx на конкретный узел, а затем укажите все соответствующие сервисы, которые вы хотите предоставить (обратите внимание на fqdn for service), как upstream, которые могут работать на нескольких узлах с таким количеством собственных nginx, как вам нужно - вам не нужно обрабатывать точные детали этого, так как k8s запускает шоу. Таким образом, у вас есть одна точка узла (ingress nginx) с известным IP-адресом, которая обрабатывает входящий трафик и перенаправляет его на сервисы внутри k8, которые могут работать на любом узле (ах). Я сосу с ascii art, но попробую:

    (outside) -> ingress (nginx) +--> my-service FQDN (running accross nodes):
                 [node-0]        |      [node-1]: my-service-pod-01 with nginx-01
                                 |      [node 2]: my-service-pod-02 with nginx-02
                                 |      ...
                                 +--> my-second-service FQDN
                                 |      [node-1]: my-second-service-pod with apache?
                                 ...
    

    В приведенном выше скриншоте у вас есть вход nginx на узле 0 (известный IP), который принимает внешний трафик, а затем обрабатывает my-service (работающую на двух модулях на двух узлах) и my-second-service (одиночный модуль) в качестве восходящих потоков. Вам нужно только выставить FQDN в сервисах, чтобы это работало, не беспокоясь о деталях IP-адресов определенных узлов. Более подробную информацию вы можете найти в документации: https://kubernetes.io/docs/tutorials/kubernetes-basics/expose/expose-intro/

    Также намного лучше, чем мой анси-арт, это представление из той же ссылки, что и в предыдущем пункте, которое иллюстрирует идею, лежащую в основе: Ingress Illustration

Обновлено для комментариев

Почему сервис не распределяет нагрузку по используемым пакетам из сервиса?

  • Это может произойти по нескольким причинам. В зависимости от того, как настроены ваши датчики живучести и готовности, возможно, служба все еще не видит модуль как неработающий. Из-за этой асинхронной природы в распределенной системе, такой как k8s, мы испытываем временную потерю запросов, когда модули удаляются во время, например, обновляемых обновлений и т.п. Во-вторых, в зависимости от того, как был настроен ваш kube-прокси, есть варианты, где вы можете ограничить его. Согласно официальной документации (https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport) с использованием --nodeport-addresses вы можете изменить поведение прокси-узла. Оказывается, что циклический перебор был старым поведением kube-прокси, очевидно, новый должен быть случайным. Наконец, чтобы исключить проблемы с подключением и сессией из браузера, вы пробовали это также из анонимного сеанса? Возможно, у вас локально кешируется днс?

Что-то еще, я убил модуль с узла 1, и при вызове узла 1 он не использовал модуль с узла 2.

  • Это немного странно. Может быть связано с вышеупомянутыми исследованиями. Согласно официальной документации, этого не должно быть. У нас был NodePort, действующий в соответствии с официальной документацией, изложенной выше: and each Node will proxy that port (the same port number on every Node) into your Service. Но если это ваш случай, то, вероятно, LB или Ingress, возможно, даже ClusterIP с внешним адресом (см. Ниже) может помочь вам.

если служба внутренняя (ClusterIP) ... выполняет ли она балансировку нагрузки для любого из модулей в узлах

  • Определенно, да. Еще одна вещь, вы можете использовать это поведение, чтобы также выставить поведение «балансировки нагрузки» в «стандартном» диапазоне портов, в отличие от 30k + от NodePort. Вот выдержка из сервисного манифеста, который мы используем для входного контроллера.

    apiVersion: v1
    kind: Service
    metadata:
        namespace: ns-my-namespace
        name: svc-nginx-ingress-example
        labels:
            name: nginx-ingress-example
            role: frontend-example
            application: nginx-example
    spec:
        selector:
            name: nginx-ingress-example
            role: frontend-example
            application: nginx-example
        ports:
        - protocol: TCP
          name: http-port
          port: 80
          targetPort: 80
        - protocol: TCP
          name: ssl-port
          port: 443
          targetPort: 443
        externalIPs:
        - 123.123.123.123
    

    Обратите внимание, что в приведенном выше примере мнимый 123.123.123.123, который отображается с externalIPs, представляет IP-адрес одного из наших рабочих узлов. Модули, работающие в сервисе svc-nginx-ingress-example, вообще не обязательно должны находиться на этом узле, но они по-прежнему направляют трафик к ним (и также распределяют нагрузку между модулями), когда этот IP-адрес попадает на указанный порт.

...