Skip to content

Latest commit

 

History

History
431 lines (332 loc) · 19.5 KB

part34-rus.md

File metadata and controls

431 lines (332 loc) · 19.5 KB

Как использовать Ingress для маршрутизации трафика на разные сервисы в Kubernetes

Оригинал

Привет, ребята, рад вас снова видеть на мастер-классе по бэкенду!

На последней лекции мы узнали, как купить доменное имя и настроить A-запись для маршрутизации запроса в наш сервис Kubernetes. В данный момент, чтобы сервис был доступен извне мы выбрали для него тип «LoadBalancer» и добавили его внешний IP-адрес в A-запись.

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

Используем Ingress для настройки A-записи

Более подходящим решением в этом случае будет использование Ingress, что позволит нам настроить A-запись только один раз, но мы сможем определить несколько правил в файле конфигурации для маршрутизации трафика на разные сервисы.

Ingress также будет заниматься балансировкой нагрузки и SSL/TLS termination, поэтому настройка HTTPS для наших сервисов будет очень простой и удобной.

Подробнее об Ingress можно прочитать на странице документации Kubernetes. По сути, Ingress связывает HTTP или HTTPS маршрутизаторы из внешнего мира с сервисом, используя правила маршрутизации, определенные в ресурсе Ingress.

Как видно на этой диаграмме,

запрос от клиента пройдет через балансировщик нагрузки, управляемый Ingress, и когда он достигнет Ingress, он будет использовать правило маршрутизации, чтобы перейти в правильный сервис и под. Если мы прокрутим немного вниз, то увидим пример минимального ресурса Ingress с простым правилом маршрутизации.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: minimal-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx-example
  rules:
  - http:
      paths:
      - path: /testpath
        pathType: Prefix
        backend:
          service:
            name: test
            port:
              number: 80

И если мы прокрутим вниз до раздела Hostname wildcards, то увидим еще один пример ресурса Ingress.

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-wildcard-host
spec:
  rules:
    - host: "foo.bar.com"
      http:
        paths:
          - pathType: Prefix
            path: "/bar"
            backend:
              service:
                name: service1
                port:
                  number: 80
    - host: "*.foo.com"
      http:
        paths:
          - pathType: Prefix
            path: "/foo"
            backend:
              service:
                name: service2
                port:
                  number: 80

который содержит 2 разных правила маршрутизации.

Как видите мы можем использовать звёздочку как маску для обозначения произвольного набора символов в правилах для направления трафика из нескольких поддоменов в один и тот же сервис.

Хорошо, теперь давайте научимся использовать Ingress в нашем кластере simple-bank.

Сначала я скопирую содержимое этого файла Ingress, а затем открою наш проект простого банковского приложения. Перед добавлением Ingress я изменю тип simple-bank API сервиса с LoadBalancer на ClusterIP, поскольку мы больше не хотим чтобы этот сервис был доступен извне.

spec:
  selector:
    app: simple-bank-api
  ports:
    - protocol: TCP
      port: 80
      targetPort: 8080
  type: ClusterIP

Затем давайте создадим новый файл ingress.yaml внутри папки eks. И вставьте содержимое примера файла Ingress, который мы только что скопировали. Первая строка файла определяет версию Kubernetes API. Вторая - содержит вид ресурса, которым является Ingress.

apiVersion: networking.k8s.io/v1
kind: Ingress

Затем следует раздел metadata, как и в других ресурсах, которые мы развернули на предыдущих лекциях. Я назову его simple-bank-ingress.

metadata:
  name: simple-bank-ingress

Теперь перейдём к разделу specification. В этом разделе мы можем определить столько правил маршрутизации, сколько захотим, чтобы перенаправлять трафик на разные сервисы. В нашем случае у нас есть только один сервис: simple-bank API, поэтому нам просто нужно добавить только одно единственное правило. В поле host я укажу api.simple-bank.org, точно так же как мы делали в А-записи домена. Далее мы можем прописать, какой HTTP-путь будет удовлетворять правилу. В нашем случае мы хотим принимать все запросы, отправляемые на хост, поэтому я изменю префикс пути на одну косую черту /.

spec:
  rules:
    - host: "api.simple-bank.org"
      http:
        paths:
          - pathType: Prefix
            path: "/"

Наконец, мы должны сообщить Ingress, куда направить запрос, указав здесь правильное имя бэкенд сервиса. Давайте скопируем имя API сервиса simple-bank из файла service.yaml и вставим его в эту строку ingress.yaml.

spec:
  ...
    backend:
      service:
        name: simple-bank-api-service
        port:
          number: 80

Мы не будем менять порт 80 для сервиса, потому что так его определили в service.yaml в одной из предыдущих лекций.

Хорошо, теперь вернемся к файлу ingress.yaml, мы можем удалить это второе правило маршрутизации,

- host: "*.foo.com"
      ...

И этого будет достаточно! Мы закончили настраивать наш ресурс Ingress.

Следующим шагом будет выполнение команды kubectl apply в терминале для его развертывания. Во-первых, я собираюсь повторно развернуть сервис, чтобы изменить его тип с LoadBalancer на ClusterIP.

kubectl apply -f eks/service.yaml
service/simple-bank-api-service configured

Итак, команда успешно выполнена! А в консоли k9s мы видим, что тип API сервиса simple-bank изменился на ClusterIP и у него больше нет внешнего IP-адреса.

Далее давайте развернем Ingress.

kubectl apply -f eks/ingress.yaml
ingress.networking.k8s.io/simple-bank-ingress created

Она тоже успешно выполнена! Был создан ресурс simple-bank-ingress. В консоли k9s мы можем поискать по ключевому слову ingress, чтобы найти его.

Вот на рисунке мы видим объект simple-bank-ingress. Он будет обрабатывать запросы, отправляемые на этот хост: api.simple-bank.org.

Если мы выведем подробную информацию об Ingress,

то увидим, что он направит трафик в бэкенд API сервис simple-bank, как мы и настроили в yaml файле. Но существует одна проблема: у этого Ingress объекта ещё нет внешнего адреса. Он пока пуст, как вы видите здесь.

Итак, как мы можем настроить A-запись домена для маршрутизации трафика на этот Ingress объект? Что ж, если вы просмотрите документацию Kubernetes, то обнаружите, что просто создать ресурс Ingress недостаточно.

Для полноценной работы у нас должен быть установлен Ingress контроллер в кластере. Итак, давайте откроем эту страницу Ingress контроллера, чтобы узнать, как его установить.

Как ясно написано здесь, в отличие от контроллеров других типов, Ingress контроллеры не запускаются автоматически вместе с кластером. Существует множество различных типов Ingress контроллеров. Мы должны выбрать один из них и развернуть его самостоятельно. На этой лекции я покажу вам, как установить Ingress контроллер nginx.

Итак, давайте откроем эту ссылку!

Она приведёт нас на GitHub страницу nginx Ingress. Затем давайте перейдем по этой ссылке «С чего начать», чтобы прочитать документацию. В зависимости от того, какой облачный провайдер вы используете, вам возможно нужно будет использовать другую команду для установки Ingress контроллера NGINX. Я использую AWS, поэтому Ingress контроллер NGINX будет находиться за сервисом балансировки сетевой нагрузки. Здесь на рисунке показана команда, которую мы должны выполнить, чтобы развернуть его в нашем Kubernetes кластере, работающем на AWS.

Давайте скопируем её и запустим в терминале!

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.2.0/deploy/static/provider/aws/deploy.yaml

Кажется она успешно выполнилась.

Чтобы проверить успешно ли запущены поды Ingress контроллера, мы можем запустить эту команду kubectl get pods.

kubectl get pods -n ingress-nginx \
    -l app.kubernetes.io/name=ingress-nginx --watch

или мы можем просто поискать по ключевому слову pods в консоли k9s. Здесь, в этом списке,

мы видим, что под ingress-nginx-controller работает в пространстве имён ingress-nginx. Итак, если мы ещё раз откроем наш simple-bank-ingress,

то увидим, что теперь у него есть внешний IP-адрес для доступа. Все, что нам нужно сделать сейчас, это скопировать этот адрес, затем вернуться на страницу Route53 Hosted zone выбрать А-запись api.simple-bank.org, нажать Edit record, вставить IP-адрес Ingress в это поле на рисунке и сохранить её!

Вот так и у нас всё готово к работе! Теперь весь трафик с поддомена api.simple-bank.org будет отправлен на наш Ingress. Чтобы убедиться, что всё работает правильно, запустим в терминале nslookup api.simple-bank.org.

nslookup api.simple-bank.org
Server: 192.168.1.254
Address: 192.168.1.254#53

Non-authoritative answer:
Name: api.simple-bank.org
Address: 54.220.48.122
Name: api.simple-bank.org
Address: 99.80.40.9
Name: api.simple-bank.org
Address: 54.229.77.174

Итак, теперь с этим доменом связано несколько IP-адресов. И если мы попытаемся запустить nslookup с адресом Ingress, он вернет тот же набор IP-адресов, как показано на рисунке.

Идеально!

Хорошо, теперь давайте попробуем отправить настоящий API-запрос к домену. Я собираюсь использовать Postman для отправки запроса на вход пользователя в систему.

И вуаля, запрос успешно выполнен.

Ingress, который мы только что настроили, работает правильно.

Тем не менее кое-что всё же следует исправить. А именно класс Ingress. На данный момент он равен None, а вместо этого должен быть Nginx.

Для этого нам нужно развернуть объект класса Ingress в кластере. Теперь, если вы используете более старую версию Kubernetes до 1.18, классы Ingress определяются, используя следующую аннотацию kubernetes.io/ingress.class в файле Ingress. Итак, в разделе metadata файла ingress.yaml мы можем добавить аннотации: kubernetes.io/ingress.class: nginx.

metadata:
  name: simple-bank-ingress
  annotations:
    kubernetes.io/ingress.class: nginx

Вот так и повторно разверните Ingress. Однако эта аннотация устарела, начиная с версии 1.18, поэтому теперь вместо неё следует использовать ресурс IngressClass.

Давайте скопируем этот пример

apiVersion: networking.k8s.io/v1
kind: IngressClass
metadata:
  name: external-lb
spec:
  controller: example.com/ingress-controller
  parameters:
    apiGroup: k8s.example.com
    kind: IngressParameters
    name: external-lb

и вставим его в начало нашего файла ingress.yaml. Мы можем использовать тройной дефис, чтобы разделить 2 ресурса в одном файле yaml. Объявление Ingress класса также начинается с версии API, а затем типа ресурса, которым является IngressClass.

apiVersion: networking.k8s.io/v1
kind: IngressClass

В разделе metadata я переименую его в nginx, а в разделе spec мы должны изменить контроллер на k8s.io/ingress-nginx.

metadata:
  name: nginx
spec:
  controller: k8s.io/ingress-nginx

Наконец, мы можем удалить все эти параметры, так как в нашем случае они не нужны.

  parameters:
    apiGroup: k8s.example.com
    kind: IngressParameters
    name: external-lb

Теперь, когда Ingress класс nginx определен, мы должны добавить его в Ingress simple-bank, в раздел spec: ingressClassName: nginx.

spec:
  ingressClassName: nginx

Имя должно совпадать с именем в разделе metadata ресурса ingressClass выше.

Хорошо, думаю этого должно быть достаточно. Давайте откроем терминал и выполним kubectl apply для повторного развертывания Ingress.

kubectl apply -f eks/ingress.yaml
ingressclass.networking.k8s.io/nginx created
ingress.networking.k8s.io/simple-bank-ingress configured

Итак, она успешно выполнена. Создался Ingress класс nginx и настроен simple-bank-ingress.

Мы можем проверить это в консоли k9s.

Как видите, класс simple-bank-ingress теперь изменился на nginx.

Превосходно!

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

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

А пока, желаю Вам получать удовольствие от обучения и до скорой встречи!