Назад | Перейти на главную страницу

Kubernetes, http-доступ к приложению в кластере

Я новичок в кубернетах. Мне нужны предложения, как получить доступ к приложению, развернутому в кластере.

У меня есть образ докера с приложением Django и Gunicorn для запуска .wsgi. Я использую этот образ для развертывания контейнеров в кластере с 3 узлами (среда для изучения k8s, 1 мастер 2 рабочих). Если я открываю службу с помощью nodePort и использую curl <node'sIP>: [порт] с сервера, не включенного в кластер, я могу связаться с приложением.

Но теперь я хочу иметь единую точку входа, которая могла бы соединяться с любой из реплик.

Я думал о создании еще одной машины, не входящей в кластер с установленным Nginx или HAproxy, но не могу найти решения, как подключить внешний обратный прокси с сервисом kubernetes.

Можете ли вы дать мне лучшее решение или предложения, как мне продолжить свою мысль?

Вам не хватает пары фундаментальных концепций Kubernetes, на которые я рекомендую вам обратить внимание:

  1. Сервисы - они обеспечивают абстракцию над вашими модулями и позволяют распределять нагрузку трафика по нескольким репликам. Их можно использовать как внутри, так и снаружи.
  2. Ingress - это позволяет вам настроить контроллер Ingress внутри вашего кластера, например Nginx, и использовать этот обратный прокси-сервер для вашего трафика для соответствующих служб. Это намного лучший подход, чем создание экземпляра Nginx за пределами вашего кластера, поскольку контроллер Ingress автоматически принимает любые новые входящие данные, которые вы создаете в своем кластере.

TL; DR

В управляемых кластерах Kubernetes типа GKE, EKS или AKS у вас есть возможность запрашивать IP-адреса для услуг у вашего облачного провайдера.

Кластеры Kubernetes, созданные например в Virtualbox используя либо kubespray,kubeadm потребуются дополнительные инструменты, чтобы получить External-IP за услуги.

Ты можешь использовать metallb назначить External-IP в кластерах, не управляемых облачным провайдером. Посетите официальный сайт:

В этом случае шаги по раскрытию приложения будут следующими:

  • Разверните модули приложений
  • Создать service прикреплен к стручкам
  • Развернуть metallb и настроить его
  • Откройте приложение одним из следующих способов:
    • Создать услугу типа LoadBalancer
    • Создать Ingress ресурс

Отказ от ответственности!

Создание Ingress ресурс требует Ingress контроллер. Я прикрепил ссылку на один из них.

Ниже я привел пример и дополнительные объяснения того, как вы можете открыть свое приложение в кластере, созданном в Virtualbox, с помощью metallb и nginx-ingress-controller.


Это пример, показывающий, как открыть приложение в кластере Kubernetes, созданном в Virtualbox, с помощью:

  • metallb
  • nginx-ingress-controller

Я разделил этот ответ на 2 части:

  • Virtualbox
  • Kubernetes

Virtualbox

Когда вы создаете свой VM's В Virtualbox у вас есть несколько способов настройки сети. Некоторые из них:

  • Bridged networking - подключение кластера Kubernetes к физической сети
  • Host-only - возможность подключения одного адаптера к узлам и хосту, обеспечивающего сетевое подключение. Для этого решения требуется либо другой адаптер с доступом в Интернет, либо шлюз (например, PfSense) с тем же Host-only сетевой адаптер подключен.

В этом примере используется клиент и 3 узла с Bridged адаптеры:

  • client с IP-адресом: 192.168.0.2
  • master с IP-адресом: 192.168.0.117
  • worker1 с IP-адресом: 192.168.0.118
  • worker2 с IP-адресом: 192.168.0.119

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

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

Kubernetes

Предположим, что:

  • Кластер настроен правильно и имеет доступ в Интернет
  • У вас есть полный доступ к этому кластеру
  • Вы можете "пинговать" каждый узел с любого другого хоста.
  • Ваш модуль отвечает на запрос порта по вашему выбору (например, 8000)

Шаги:

  • Создайте контейнер с gunicorn
  • Создайте определение службы для gunicorn стручок
  • Развернуть Metallb
  • Выставить приложение с сервисом типа LoadBalancer
  • Открыть приложение с помощью Ingress ресурс

Создайте контейнер с gunicorn

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

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gunicorn
spec:
  selector:
    matchLabels:
      app: gunicorn
  replicas: 1
  template:
    metadata:
      labels:
        app: gunicorn
    spec:
      containers:
      - name: gunicorn
        image: ubuntu
        command:
        - sleep
        - "infinity"

я использовал ubuntu изображение, которое я exec`d и выполните следующие команды:

  • $ apt update && apt install -y python3 python3-pip
  • $ pip3 install gunicorn

Пример кода, который я использовал myapp.py:

def app(environ, start_response):
    data = b"Hello, World!\n"
    start_response("200 OK", [
        ("Content-Type", "text/plain"),
        ("Content-Length", str(len(data)))
    ])
    return iter([data])
  • $ gunicorn -w 1 -b 0.0.0.0 myapp:app &

Приведенный выше пример основан на:

После этого ваш под должен ответить на порт. 8000 с участием Hello, World!.

Создайте определение службы для gunicorn стручок

Определение службы для gunicorn стручок:

apiVersion: v1
kind: Service
metadata:
  name: gunicorn-service
spec:
  selector:
    app: gunicorn
  ports:
    - name: gunicorn-port
      port: 8000
      targetPort: 8000
  type: NodePort

Развернуть Metallb

После официального Metallb документация: Metallb.universe.tf: Установка:

  • редактировать kube-proxy изменить strictARP режим от false к true:
    • $ kubectl edit configmap -n kube-system kube-proxy
  • $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/namespace.yaml
  • $ kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.9.3/manifests/metallb.yaml
  • $ kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)

Вам также нужно будет добавить configMap это скажет metallb какие IP-адреса он мог выделить для сервисов:

apiVersion: v1
kind: ConfigMap
metadata:
  namespace: metallb-system
  name: config
data:
  config: |
    address-pools:
    - name: default
      protocol: layer2
      addresses:
      - 192.168.0.240-192.168.0.250

Пожалуйста, обратите внимание на деталь:

      addresses:
      - 192.168.0.240-192.168.0.250

Убедитесь, что этот диапазон адресов не перекрывает какие-либо используемые адреса в вашей сети и что он находится в той же сети, что и узлы, и клиент.

После этого вы сможете создать сервис типа LoadBalancer который получит IP-адрес.

Выставить приложение с сервисом типа LoadBalancer

Вы должны уметь запускать:

  • $ kubectl expose deployment gunicorn --type=LoadBalancer --port=8000

Выход $ kubectl get services должен показать:

NAME               TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)          AGE
gunicorn           LoadBalancer   10.233.43.104   192.168.0.240   8000:32591/TCP   3s
gunicorn-service   NodePort       10.233.34.96    <none>          8000:30862/TCP   73s
kubernetes         ClusterIP      10.233.0.1      <none>          443/TCP          23h

как вы видете gunicorn сервис имеет EXTERNAL-IP из 192.168.0.240 который находится в пуле IP-адресов metallb.

Физическая сеть, используемая в этом примере: 192.168.0.0/24

Вы можете запустить: curl 192.168.0.240:8000 и получить: Hello, World!

Открыть приложение с помощью Ingress ресурс

Вам нужно будет развернуть Ingress контроллер перед открытием вашего приложения. Вы можете развернуть nginx-ingress-controller запустив:

  • $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/provider/cloud/deploy.yaml

это Ingress у контроллера будет тип службы LoadBalancer прикреплен к нему, и это будет входная точка по запросу.

Вы можете получить его IP-адрес, вызвав: $ kubectl get svc -n ingress-nginx:

NAME                                 TYPE           CLUSTER-IP      EXTERNAL-IP     PORT(S)                      AGE
ingress-nginx-controller             LoadBalancer   10.233.52.8     192.168.0.241   80:31380/TCP,443:30066/TCP   29m
ingress-nginx-controller-admission   ClusterIP      10.233.37.255   <none>          443/TCP                      29m

Здесь Ingress определение для маршрутизации трафика от контроллера к вашему модулю:

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gunicorn-ingress
  annotations:
    kubernetes.io/ingress.class: "nginx"
spec:
  rules:
  - host: 
    http:
      paths:
      - path: /
        backend:
          serviceName: gunicorn-service
          servicePort: gunicorn-port

После его применения вы сможете:

  • curl 192.168.0.241 и получить ответ от gunicorn