Запросить демо
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Дополнительные услуги
Оставить заявку
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Узнать стоимость
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Дополнительные услуги
Попробовать бесплатно
Я подтверждаю свое согласие на обработку компанией КРОК моих персональных данных, указанных в форме, в целях и пределах, установленных законодательством РФ о персональных данных в рамках проводимых мероприятий в течение неопределенного срока
Дополнительные услуги
Быть в теме

Kubernetes: использование Ingress

14.08.2018 19 минут 2099

В этой статье будет показано, как организовать удобную балансировку трафика на ваши приложения при помощи встроенной в Kubernetes функциональности – Ingress.

В одной из прошлых статей “Kubeadm: создание Kubernetes кластера за 10 минут” было показано, как быстро развернуть собственный кластер Kubernetes, а также развернуть внутри него демо-приложение Sock-Shop. Далее в статье “Kubernetes: постоянные диски на GlusterFS и heketi” мы обсудили, как организовать пространство для постоянных дисков контейнеров внутри вашего кластера на базе GlusterFS.

Решаемая проблема

В этой статье будет показано, как организовать удобную балансировку трафика на ваши приложения при помощи встроенной в Kubernetes функциональности — Ingress. Эта функциональность является особенно полезной в случаях, когда вы используете Kubernetes в системе виртуализации или облаке, для которого в Kubernetes нет поддержки функциональности LoadBalancer . Выполняя инструкции из первой статьи вы наверняка заметили, что публикация приложения Sock-Shop на всех вычислительных узлах кластера при помощи функциональности NodePort совершенно не удобна с точки зрения поддержки приложения, т.к. при таком подходе придется использовать внешний балансировщик трафика и держать на нем в актуальном состоянии список всех вычислительных хостов вашего кластера, а также список актуальных опубликованных приложений. А это задача не тривиальная.



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



Ingress— это набор правил внутри вашего кластера, предназначенных для того, чтобы входящие подключения могли достичь сервисов (Services) ваших приложений.



    Основные задачи, которые решает Ingress:
  • Организация для ваших приложений внешне доступных URL
  • Обеспечение балансировки трафика
  • Терминация SSL
  • Виртуальный хостинг на основе имен и т.д


В Kubernetes Ingress работает в паре с IngressController-ом следующим образом: в Ingress описываются правила балансировки трафика до сервисов ваших приложений, применяемые внутри балансировщика, который представляет собой ни что иное, как отдельный Pod с упакованным в него Nginx, Traefik и т.д.

Описание решения

В качестве практического решения данной задачки мне очень понравился элегантный подход, описанный в статье " Kubernetes, Ingress Controllers and Traefik " создателями балансировщика Traefik . Архитектурная схема кластера, реализующего этот подход, приведена на рисунке ниже.

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

    Именно этот подход мы и воплотим в жизнь, добавив к нашему уже существующему кластеру один или несколько дополнительных серверов, которые будут предназначены исключительно для запуска IngressController-ов. Также мы создадим отдельный IngressController для опубликованного ранее приложения Sock-Shop, и сделаем это приложение доступным по 80 порту сервера-балансировщика (edge-router.comp.avmaksimov.ru). В качестве балансировщика трафика будет использоваться Nginx , однако вы легко можете заменить его на Traefik или любой другой IngressController. Архитектура созданного ранее кластера изменится и будет выглядеть следующим образом:

    plcvb.png

Настройка сервера для хостинга балансировщиков

Добавьте к вашему кластеру Kubernetes отдельный вычислительный сервер. Настройка сервера выполняется так же, как это было сделано в статье " Kubeadm: создание Kubernetes кластера за 10 минут ".

Чтобы запретить кластеру Kubernetes запускать на сервере-балансировщике какие-либо Pod-ы кроме IngressController-ов, необходимо перевести добавленный сервер в режим обслуживания :

kubectl drain edge-router.comp.avmaksimov.ru —ignore-daemonsets

Флаг —ignore-daemonsets используется для того, чтобы мы могли использовать виртуализацию сети и запускать IngressController-ы, определяя их как DaemonSet-ы.

Также этот сервер необходимо как-то пометить, например, присвоив ему метку ( label ) role=edge-router:

kubectl label nodes edge-router.comp.avmaksimov.ru role=edge-router

После этих нехитрых манипуляций, все IngressController-ы балансировщиков, запускаемых как DaemonSet-ы с селектором узла (nodeSelector) role: edge-router будут попадать именно на этот сервер.

Пример балансировки трафика для приложения sock-shop

Предполагается, что вы запустили внутри своего кластера демо-приложение Sock-Shop. Если нет, сделайте это, пожалуйста, в противном случае вы не сможете продолжить далее. Как только приложение Sock-Shop запустится, его сервис front-end начнет принимать и обслуживать для него внешний трафик на 80 порту. Именно этот порт экспортирован в порт 30001 на каждом вычислительном узле вашего кластера.

Установка IngressController-А

Для каждого отдельного сервиса приложения, перед которым вы хотите поставить балансировщик, необходимо разворачивать отдельный IngressController. Для приложения Sock-Shop это делается следующим образом.


TLSсертификат


Обязательным требованием для работы IngressController-а является TLS сертификат. Создать его можно командой:

openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout tls.key -out tls.crt -subj «/CN=socks.comp.avmaksimov.ru/O=nginx»

Далее необходимо опубликовать этот сертификат в качестве секрета ( Secrets ):

kubectl create secret tls tls-secret —key tls.key —cert tls.crt


DefaultBackend


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


kubectl create -f default-backend.yaml

Содержание default-backend.yaml:

apiVersion: extensions/v1beta1

kind: Deployment

metadata:

name: default-http-backend

labels:

k8s-app: default-http-backend

namespace: kube-system

spec:

replicas: 1

template:

metadata:

labels:

k8s-app: default-http-backend

spec:

terminationGracePeriodSeconds: 60

containers:

— name: default-http-backend

# Any image is permissable as long as:

# 1. It serves a 404 page at /

# 2. It serves 200 on a /healthz endpoint

image: gcr.io/google_containers/defaultbackend:1.0

livenessProbe:

httpGet:

path: /healthz

port: 8080

scheme: HTTP

initialDelaySeconds: 30

timeoutSeconds: 5

ports:

— containerPort: 8080

resources:

limits:

cpu: 10m

memory: 20Mi

requests:

cpu: 10m

memory: 20Mi

---

apiVersion: v1

kind: Service

metadata:

name: default-http-backend

namespace: kube-system

labels:

k8s-app: default-http-backend

spec:

ports:

— port: 80

targetPort: 8080

selector:

k8s-app: default-http-backend


Запуск балансировщика


После того как определены бекенд по-умолчанию и TLS-сертификат для Nginx IngressController-а, можно выполнить его запуск:

kubectl create -f nginx-ingress-controller.yaml

Содержание nginx-ingress-controller.yaml:

apiVersion: extensions/v1beta1

kind: DaemonSet

metadata:

name: nginx-ingress-controller

labels:

k8s-app: nginx-ingress-controller

namespace: kube-system

spec:

template:

metadata:

labels:

k8s-app: nginx-ingress-controller

spec:

# hostNetwork makes it possible to use ipv6 and to preserve the source IP correctly regardless of docker configuration

# however, it is not a hard dependency of the nginx-ingress-controller itself and it may cause issues if port 10254 already is taken on the host

# that said, since hostPort is broken on CNI ( https://github.com/kubernetes/kubernetes/issues/31307 ) we have to use hostNetwork where CNI is used

# like with kubeadm

hostNetwork: true

terminationGracePeriodSeconds: 60

containers:

— image: gcr.io/google_containers/nginx-ingress-controller:0.9.0-beta.2

name: nginx-ingress-controller

readinessProbe:

httpGet:

path: /healthz

port: 10254

scheme: HTTP

livenessProbe:

httpGet:

path: /healthz

port: 10254

scheme: HTTP

initialDelaySeconds: 10

timeoutSeconds: 1

ports:

— containerPort: 80

hostPort: 80

— containerPort: 443

hostPort: 443

env:

— name: POD_NAME

valueFrom:

fieldRef:

fieldPath: metadata.name

— name: POD_NAMESPACE

valueFrom:

fieldRef:

fieldPath: metadata.namespace

args:

— /nginx-ingress-controller

— —default-backend-service=$(POD_NAMESPACE)/default-http-backend

nodeSelector:

role: edge-router


Определение правил для балансировки


После того, как запущен IngressController, можно создать сущность Ingress, в которой определить как именно наше демо приложение будет видно из интернета. Для этого выполните следующую команду:


kubectl create -f socks-ingress.yaml

Содержание socks-ingress.yaml:

apiVersion: extensions/v1beta1

kind: Ingress

metadata:

name: front-end

namespace: sock-shop

spec:

rules:

— host: socks.comp.avmaksimov.ru

http:

paths:

— path: /

backend:

serviceName: front-end

servicePort: 80


В данном примере мы сообщаем IngressController-у, что сервис front-end, находящийся в пространстве имен sock-shop и слушающий трафик на 80 порту, будет доступен извне по URL socks.comp.avmaksimov.ru (указывает на внешний IP-адрес сервера edge-router.comp.avmaksimov.ru ).

После всех данных операций демо-приложение Sock-Shop стало доступно на внешнем IP-адресе сервера-балансировщика edge-router.comp.avmaksimov.ru и открывается по URL socks.comp.avmaksimov.ru .

Заключение

Как видите, при помощи сущностей типа Ingress и IngressController можно легко и просто публиковать приложения, развернутые внутри вашего Kubernetes кластера, во внешние сети. Другие особенности работы с балансировщиками в Kubernetes будут освещены по вашим запросам.

Сервисы упоминаемые в статье

  1. Публичное облако КРОК

Не пропустите самые важные, интересные и полезные статьи недели

Ваш e-mail успешно подписан.

Смотрите также