Предоставление нескольких служб TCP / UDP с использованием одного LoadBalancer на K8s - PullRequest
2 голосов
/ 25 апреля 2020

Попытка выяснить, как представить несколько служб TCP / UDP, используя один LoadBalancer в Kubernetes. Допустим, сервисами являются ftpsrv1.com и ftpsrv2.com, каждый из которых обслуживает порт 21.

Вот варианты, которые я могу придумать, и их ограничения:

  • Один фунт на св c: слишком дорого.
  • Nodeport: хотите использовать порт вне диапазона 30000-32767.
  • K8s Ingress: на данный момент не поддерживает службы TCP или UDP.
  • Использование Nginx Входной контроллер: который снова будет отображаться один на один :
  • Найдена эта пользовательская реализация : Но, похоже, она не обновлена , последнее обновление было почти год go.

Любые входные данные будут высоко оценены.

Ответы [ 2 ]

2 голосов
/ 27 апреля 2020

На самом деле возможно сделать это, используя NGINX Ingress.

Ingress не поддерживает службы TCP или UDP. По этой причине этот контроллер Ingress использует флаги --tcp-services-configmap и --udp-services-configmap для указания на существующую карту конфигурации, где ключ - это используемый внешний порт, а значение указывает службу, доступную для использования в формате: <namespace/service name>:<service port>:[PROXY]:[PROXY].

В этом руководстве описывается, как этого можно достичь с помощью мини-куба, но выполнение этого в локальном kubernetes отличается и требует нескольких дополнительных шагов.

Отсутствует документация, описывающая, как это можно сделать в системе, не являющейся мини-кубом, и поэтому я решил go выполнить все шаги здесь. В этом руководстве предполагается, что у вас кластер fre sh без установленного NGINX Ingress.

Я использую кластер GKE, и все команды выполняются с моей рабочей станции Linux. Это можно сделать и на кластере Bare Metal K8S.

Создание примера приложения и службы

Здесь мы собираемся создать и приложение, и его сервис, чтобы предоставить его позже, используя наш вход.

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-deployment
  namespace: default
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
      - image: redis
        imagePullPolicy: Always
        name: redis
        ports:
        - containerPort: 6379
          protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
  name: redis-service
  namespace: default
spec:
  selector:
    app: redis
  type: ClusterIP
  ports:
    - name: tcp-port
      port: 6379
      targetPort: 6379
      protocol: TCP
---      
apiVersion: v1
kind: Service
metadata:
  name: redis-service2
  namespace: default
spec:
  selector:
    app: redis
  type: ClusterIP
  ports:
    - name: tcp-port
      port: 6380
      targetPort: 6379
      protocol: TCP      

Обратите внимание, что мы создаем 2 разных сервиса для одного и того же приложения. Это только для подтверждения концепции. Я не хочу показывать, что многие порты могут быть сопоставлены с использованием только одного входа.

Установка NGINX Вход с использованием шлема:

Установка шлема 3:

$ curl https://raw.githubusercontent.com/helm/helm/master/scripts/get-helm-3 | bash

Добавление NGINX Входной репозиторий:

$ helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx

Установка NGINX Вход в пространство имен системы kube:

$ helm install -n kube-system ingress-nginx ingress-nginx/ingress-nginx

Подготовка нашего нового NGINX Развертывание контроллера входа

Мы должны добавить следующие строки под spe c .template.spe c .containers.args:

        - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
        - --udp-services-configmap=$(POD_NAMESPACE)/udp-services

Поэтому мы должны отредактировать с помощью следующей команды:

$ kubectl edit deployments -n kube-system ingress-nginx-controller

И сделать это выглядит так:

...
    spec:
      containers:
      - args:
        - /nginx-ingress-controller
        - --publish-service=kube-system/ingress-nginx-controller
        - --election-id=ingress-controller-leader
        - --ingress-class=nginx
        - --configmap=kube-system/ingress-nginx-controller
        - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
        - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
        - --validating-webhook=:8443
        - --validating-webhook-certificate=/usr/local/certificates/cert
        - --validating-webhook-key=/usr/local/certificates/key
...

Создание карт конфигурации служб tcp / udp

apiVersion: v1
kind: ConfigMap
metadata:
  name: tcp-services
  namespace: kube-system
apiVersion: v1
kind: ConfigMap
metadata:
  name: udp-services
  namespace: kube-system

Поскольку эти конфигурации являются централизованными и могут содержать конфигурации, они Лучше всего, если мы исправляем их, а не перезаписываем каждый раз при добавлении службы:

$ kubectl patch configmap tcp-services -n kube-system --patch '{"data":{"6379":"default/redis-service:6379"}}'
$ kubectl patch configmap tcp-services -n kube-system --patch '{"data":{"6380":"default/redis-service2:6380"}}'

Где:

  • 6379: порт вашей службы должен прослушивать извне виртуальную машину minikube
  • default: пространство имен, в котором установлена ​​ваша служба
  • * 107 2 *: имя службы

Мы можем проверить, что наш ресурс был исправлен с помощью следующей команды:

$ kubectl get configmap tcp-services -n kube-system -o yaml

apiVersion: v1
data:
  "6379": default/redis-service:6379
  "6380": default/redis-service2:6380
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ConfigMap","metadata":{"annotations":{},"name":"tcp-services","namespace":"kube-system"}}
  creationTimestamp: "2020-04-27T14:40:41Z"
  name: tcp-services
  namespace: kube-system
  resourceVersion: "7437"
  selfLink: /api/v1/namespaces/kube-system/configmaps/tcp-services
  uid: 11b01605-8895-11ea-b40b-42010a9a0050

Единственное значение, которое вам нужно проверить, - это наличие значение в свойстве data, которое выглядит следующим образом:

  "6379": default/redis-service:6379
  "6380": default/redis-service2:6380

Добавление портов в NGINX Развертывание Ingress Controller

Нам нужно исправить наш nginx входящий контроллер, который прослушивает порты 6379/6380 и может направлять трафик c к вашему сервису.

spec:
  template:
    spec:
      containers:
      - name: controller
        ports:
         - containerPort: 6379
           hostPort: 6379
         - containerPort: 6380
           hostPort: 6380 

Создайте файл с именем nginx-ingress-controller-patch.yaml и вставьте содержимое выше.

Затем примените изменения с помощью следующей команды:

$ kubectl patch deployment ingress-nginx-controller -n kube-system --patch "$(cat nginx-ingress-controller-patch.yaml)"

Добавьте порты в NGINX Служба Ingress Controller

В отличие от решения, представленного для Minikube, мы придется исправлять наш NGINX Ingress Controller Service, так как он отвечает за разоблачение этих портов.

spec:
  ports:
  - nodePort: 31100
    port: 6379
    name: redis
  - nodePort: 31101
    port: 6380
    name: redis2

Создайте файл с именем nginx-ingress-svc-controller-patch.yaml и вставьте содержимое выше.

Затем примените изменения с помощью следующей команды:

$ kubectl patch service ingress-nginx-controller -n kube-system --patch "$(cat nginx-ingress-controller-patch.yaml)"

Проверка наш сервис

$ kubectl get service -n kube-system ingress-nginx-controller
NAME                       TYPE           CLUSTER-IP      EXTERNAL-IP    PORT(S)                                                    AGE
ingress-nginx-controller   LoadBalancer   10.15.251.203   34.89.108.48   6379:31100/TCP,6380:31101/TCP,80:30752/TCP,443:30268/TCP   38m

Обратите внимание, что наш ingress-nginx-controller прослушивает порты 6379/6380.

Проверьте, что вы можете обратиться к вашему сервису с помощью te lnet с помощью следующей команды:

$ telnet 34.89.108.48 6379

Вы должны увидеть следующий вывод:

Trying 34.89.108.48...
Connected to 34.89.108.48.
Escape character is '^]'.

Для выхода te lnet введите одновременно клавиши Ctrl и ]. Затем введите quit и нажмите enter.

Мы также можем протестировать порт 6380:

$ telnet 34.89.108.48 6380
Trying 34.89.108.48...
Connected to 34.89.108.48.
Escape character is '^]'.

Если вы не смогли подключиться, пожалуйста, проверьте ваши шаги выше.

Статьи по теме

0 голосов
/ 25 апреля 2020

Относительно «Nodeport: хотите использовать порт за пределами диапазона 30000-32767».

Вы можете вручную выбрать порт для своей службы для каждой реализации службы с помощью настройки «nodePort» в файл yaml службы или установите флаг, указанный ниже, чтобы пользовательский диапазон портов автоматически выделялся для всех реализаций службы.

Из документов: «Если вы установите поле типа в NodePort, плоскость управления Kubernetes выделяет порт из диапазона, указанного в флаге --service-node-port-range (по умолчанию: 30000-32767). " Услуги

...