[IT-инфраструктура, DevOps, Openshift] Все об OpenShift Egress. Часть 1

Автор Сообщение
news_bot ®

Стаж: 6 лет 9 месяцев
Сообщений: 27286

Создавать темы news_bot ® написал(а)
12-Ноя-2020 13:30


Про управление входящим в OpenShift трафиком (оно же Ingress) написано много в документации и различных статьях по его настройке. Но, кроме контроля входящего в кластер трафика, в работе зачастую требуется контроль исходящего трафика (Egress). А на эту тему информации, систематизирующей подходы и технические решения, значительно меньше. Постараемся заполнить эту нишу серией постов.
Итак, в каких ситуациях нужен контроль исходящего из кластера трафика?
Можно выделить три типовых сценария использования.
Доступ к внешнему ресурсу контролируется извне кластера
Например, есть внешняя база данных, доступ к которой контролируется межсетевым экраном, и требуется предоставить доступ к этой БД только для определенных POD кластера. По умолчанию POD при взаимодействии с внешними ресурсами используют IP-адрес узла кластера, поэтому задача не решается «в лоб».
Можно выделить несколько узлов исключительно под эти POD, но это зачастую не выход. Узлов понадобится несколько (нам же нужна отказоустойчивость), а требуемых POD может быть совсем немного. Узлы могут получать IP адреса по DHCP, что также затрудняет решение проблемы. Ну и, наконец, таких внешних «зон безопасности» может быть много, и выделять под каждую по два узла совсем не хочется.
Для определенных POD в кластере требуется доступ в изолированные сегменты сети
Типичным случаем здесь является организация доступа определенных POD к сегментам сети, расположенным в другом VLAN (которого нет на узлах кластера) или вообще на другом оборудовании (например, по требованиям PCI DSS).
Создавать по кластеру в каждом таком сегменте — дорого и к тому же тяжело поддерживать. А заводить требуемый VLAN на узлы кластера не будут: его для этого и сделали, чтобы доступ получило только то ПО и оборудование, которое участвует в этом критичном с точки зрения ИБ бизнес-процессе.
К пропускной способности или задержкам сети определенных POD предъявляются особые требования
Например, приложение требует для нормальной работы выделенного соединения 10G Ethernet и полностью его утилизирует. В этом случае также непонятно, как обеспечить эти требования в условиях одновременной работы десятков или сотен POD на одном рабочем узле. Не выделять же полностью узел кластера под один подобный POD.
На все вышеописанные сценарии есть решения, которые связаны с управлением исходящего из кластера OpenShift трафика. Попробуем разобраться, в каком случае какое решение по Egress применять, и как оно работает.
Egress IP и Egress Router
Static IP Egress
В OpenShift, начиная с версии 3.7, появилась возможность выделить фиксированные адреса на namespace, и именно с этих адресов все POD в этом namespace будут обращаться к внешним ресурсам кластера. Реализовано это средствами OpenShift SDN.
Как это работает:
  • Создадим проект «egress» и запустим в нем тестовый POD «tool»:
    [ocp@shift-is01 ~]$ oc new-project egress
    Now using project «egress» on server «https://api.ocp4.demo.local:6443».
    [ocp@shift-is01 ~]$ kubectl run tool -it --image=rhel7/rhel-tools  --restart=Never -- bash
    If you don't see a command prompt, try pressing enter.
  • Выполним запрос к внешнему серверу с POD и посмотрим, с какого адреса мы пришли:
    [root@tool /]# curl www.ocp4.demo.local:8080/test
    Hello !
    [root@shift-is01 httpd]# tail -f ./access_log
    192.168.111.204 — - [30/Oct/2020:14:00:32 +0300] «GET /test HTTP/1.1» 200 8 «-» «curl/7.29.0»
  • Видно, что «наружу» из POD tool мы попадаем с узла кластера shift-worker1:
    [ocp@shift-is01 ~]$ oc get pod tool -o jsonpath='{ .status.hostIP }{»\n»}'
    192.168.111.204
    [ocp@shift-is01 ~]$ oc get hostsubnets.network.openshift.io shift-worker0 shift-worker1
    NAME            HOST            HOST IP           SUBNET          EGRESS CIDRS   EGRESS IPS
    shift-worker0   shift-worker0   192.168.111.203   10.254.3.0/24
    shift-worker1   shift-worker1   192.168.111.204   10.254.4.0/24
  • Присвоим по одному статическому IP-адресу для egress на два узла кластера и укажем, что эти адреса должны использоваться для egress трафика в namespace «egress»:
    [ocp@shift-is01 egress]$ oc patch hostsubnet shift-worker0 --type=merge -p '{«egressIPs»: [«192.168.111.225»]}'
    hostsubnet.network.openshift.io/shift-worker0 patched
    [ocp@shift-is01 egress]$ oc patch hostsubnet shift-worker1 --type=merge -p '{«egressIPs»: [«192.168.111.226»]}'
    hostsubnet.network.openshift.io/shift-worker1 patched
    [ocp@shift-is01 egress]$ oc patch netnamespace egress --type=merge -p '{«egressIPs»: [«192.168.111.225», «192.168.111.226»]}'
    netnamespace.network.openshift.io/egress patched
  • После этого OpenShift создаст network alias на основном интерфейсе узла (интерфейс с суффиксом :eip, то есть интерфейс для egress IP):
    [ocp@shift-is01 egress]$ ssh core@shift-worker0 ip a show dev ens192
    2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 00:50:56:96:48:19 brd ff:ff:ff:ff:ff:ff
        inet 192.168.111.203/24 brd 192.168.111.255 scope global noprefixroute ens192
           valid_lft forever preferred_lft forever
        inet 192.168.111.225/24 brd 192.168.111.255 scope global secondary ens192:eip
           valid_lft forever preferred_lft forever
        inet6 fe80::250:56ff:fe96:4819/64 scope link
           valid_lft forever preferred_lft forever
    [ocp@shift-is01 egress]$ ssh core@shift-worker1 ip a show dev ens192
    2: ens192: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
        link/ether 00:50:56:96:0c:ef brd ff:ff:ff:ff:ff:ff
        inet 192.168.111.204/24 brd 192.168.111.255 scope global noprefixroute ens192
           valid_lft forever preferred_lft forever
        inet 192.168.111.226/24 brd 192.168.111.255 scope global secondary ens192:eip
           valid_lft forever preferred_lft forever
        inet6 fe80::250:56ff:fe96:cef/64 scope link
           valid_lft forever preferred_lft forever
  • Теперь при запуске обращения из нашего контейнера видно, что мы приходим к WEB-серверу с назначенного Egress адреса:
    [root@shift-is01 httpd]# tail -f ./access_log
    192.168.111.225 — - [30/Oct/2020:15:17:05 +0300] «GET /test HTTP/1.1» 200 8 «-» «curl/7.29.0»

Всё работает, но непонятно, как именно:) Например, контейнер, как мы видели ранее, работает на узле shift-worker1. На этот узел был назначен адрес Egress IP = 192.168.111.226. Так почему же мы выходим из кластера с Egress IP = 192.168.111.225?
Ответ на этот вопрос дает статья How to Enable Static Egress IP in OCP. Давайте с ее помощью выясним, что же происходит «под капотом» OpenShift при использовании Egress IP.
  • В таблице NAT в iptables на shift-worker1 есть такие строчки:
    ---- skipped -----
    Chain OPENSHIFT-MASQUERADE (1 references)
    target     prot opt source               destination
    SNAT       all  --  10.254.0.0/16        anywhere             mark match 0xe28820 to:192.168.111.226
    RETURN     all  --  anywhere             anywhere             mark match 0x1/0x1
    OPENSHIFT-MASQUERADE-2  all  --  10.254.0.0/16        anywhere             /* masquerade pod-to-external traffic */

    То есть iptables на этом узле изменит source address на 192.168.111.226 для всех пакетов c меткой 0xe28820. Аналогичная картина будет и на shift-worker0, только адрес для трансляции будет 192.168.111.225.
  • Осталось выяснить, откуда берется эта метка. А метку ставит OpenShift SDN на все пакеты, которые выходят из namespace «egress».
    Принадлежность к проекту определяется его virtual network ID (VNID), в нашем случае 0xe28820 — это шестнадцатеричное значение VNID для проекта egress.
    OpenShift SDN заворачивает все подобные пакеты в tunnel interface vxlan0 с указанием, что доставить пакет надо на хост shift-worker0:
    [root@shift-worker1 ~]# ovs-ofctl -O OpenFlow13 dump-flows br0 table=100
    ---- skipped -----
    cookie=0x0, duration=4106.403s, table=100, n_packets=6, n_bytes=496, priority=100,ip,reg0=0xe28820 actions=ct(commit),move:NXM_NX_REG0[]->NXM_NX_TUN_ID[0..31],set_field:192.168.111.203->tun_dst,output:vxlan0

    Таким образом, OpenShift SDN выбирает «основной» Egress IP-адрес, и все пакеты с проекта помечает меткой и отправляет на хост, содержащий «основной» Egress IP. На этом хосте iptables выполняет Source NAT, и задача решена. Если хост с «основным» Egress IP становится недоступен, то пакеты перенаправляются на следующий в списке Egress IP-адресов хост (в нашем случае это будет shift-worker1).
    Если мы выключим хост shift-worker0, то наш тестовый POD «наружу» будет выходить уже с адресом 192.168.111.226, который мы присвоили узлу shift-worker1:
    192.168.111.226 — — [30/Oct/2020:15:28:38 +0300] «GET /test HTTP/1.1» 200 8 «-» «curl/7.29.0»
    Именно поэтому нам нужно как минимум два IP-адреса при использовании Egress IP. В случае отказа одного узла кластера POD мы сможем получить доступ к внешним ресурсам с заданных IP.

Описанная здесь схема организации Egress хорошо подходит для первого сценария использования, когда доступ к внешним по отношению к кластеру ресурсам определяется межсетевым экраном или самим ресурсом. Применительно к нашему стенду все POD в проекте «egress» (POD2 – POD4) при обращении «наружу» получат заранее определенные адреса (192.168.111.225 или 192.168.111.225) вне зависимости от того, на каком узле кластера они находятся. Остальные POD кластера при обращении к внешним ресурсам получат IP-адрес узла кластера и будут отвергнуты либо МЭ, либо приложением.

Subnet IP Egress
Если нужно сделать фиксированные Egress-адреса для нескольких проектов, то использовать Egress IP неудобно. В этом случае узлам кластера можно указать, какую подсеть использовать, а проекту — какой IP адрес из этой подсети взять.
[ocp@shift-is01 egress]$ oc patch hostsubnet shift-worker0 --type=merge -p '{«egressCIDRs»: [«192.168.111.224/29»]}'
hostsubnet.network.openshift.io/shift-worker0 patched
[ocp@shift-is01 egress]$ oc patch hostsubnet shift-worker1 --type=merge -p '{«egressCIDRs»: [«192.168.111.224/29»]}'
hostsubnet.network.openshift.io/shift-worker1 patched
[ocp@shift-is01 egress]$ oc get hostsubnets.network.openshift.io shift-worker0 shift-worker1
NAME            HOST            HOST IP           SUBNET          EGRESS CIDRS             EGRESS IPS
shift-worker0   shift-worker0   192.168.111.203   10.254.3.0/24   [«192.168.111.224/29»]
shift-worker1   shift-worker1   192.168.111.204   10.254.4.0/24   [«192.168.111.224/29»]

После этого указываем проекту, какой IP-адрес использовать для исходящего трафика:
[ocp@shift-is01 egress]$ oc patch netnamespace egress --type=merge -p '{«egressIPs»: [«192.168.111.225»]}'
netnamespace.network.openshift.io/egress patched
[ocp@shift-is01 egress]$ oc get netnamespaces egress
NAME     NETID      EGRESS IPS
egress   14807624   [«192.168.111.225»]

Разумеется, egressCIDR должен быть в той же подсети, что и основной IP-адрес узла. И выделять два адреса на проект в данном случае не требуется — при отказе узла используемый адрес «переедет» на другой доступный узел с установленным egressCIDR (при условии, что этот адрес в него входит).
Egress Router
Рассказывая про Egress в OpenShift, важно также упомянуть про Egress router. Он применялся еще до того, как появилась возможность контролировать исходящий трафик средствами Openshift SDN. В качестве решения использовался специальный POD, у которого один адрес находился в кластерной сети OpenShift, а другой получал внешний IP-адрес и доступ к физическому интерфейсу узла через macvlan CNI plugin.
Этот POD выступал в роли маршрутизатора между внутренней сетью кластера и внешними сетями за пределами OpenShift. Пример управления исходящим трафиком через Egress router можно посмотреть на странице Red Hat OpenShift Blog. Но так как конфигурация на базе OpenShfit SDN проще в настройке и поддержке, описание решения на базе Egress router в OpenShift версии 4 удалено из документации.
Vanilla Kubernetes
А что с управлением Egress трафиком в «ванильном» Kubernetes? К сожалению, единого решения здесь нет. Все зависит от возможностей SDN, который используется в работе кластера. Например, Calico позволяет отключить Source NAT для определенного пула IP-адресов. Но в этом случае вопросы маршрутизации трафика между POD кластера и внешним миром придется решать самостоятельно.
Резюме
В OpenShift можно штатными средствами SDN организовать контроль IP-адресации исходящего трафика, чтобы обеспечить требования внешних систем контроля доступа. При этом необходимо понимать возникающие в работе кластера технические нюансы:
  • Весь исходящий трафик от проекта с фиксированным Egress IP будет направлен через один узел кластера вне зависимости от того, где находятся POD этого проекта. Если у вас на кластере большая нагрузка на сетевую подсистему, то это может увеличить задержки в передаче данных;
  • Network alias для Egress IP будет создан на первом с точки зрения OC интерфейсе. Поэтому, если на узлах несколько интерфейсов, необходимо, чтобы «основной» из них был первым;
  • Вам придется заняться IP address management для Egress IP. Это очевидно: раз вы сами занимаетесь выделением IP, то и контроль за корректностью тоже будет за вами.

Описанные выше способы организации Egress прекрасно помогают решить проблемы, когда нам нужно для определенных проектов получить фиксированные и отдельные от кластера IP адреса для исходящего трафика. Но что делать, если нам необходимо попасть в другой VLAN?
Подмена IP-адресов здесь никак не поможет. Решением является использование CNI «meta-plugin» Multus. Multus CNI plugin стал доступен в качестве поддерживаемого компонента в OpenShift 4.1 и фактически позволяет организовать подключение POD к нескольким сетям одновременно.
Настройке и использованию Multus CNI Plugin в OpenShift посвятим вторую часть этого поста.
До встречи!
Список литературы
https://docs.openshift.com/container-platform/4.6/networking/openshift_sdn/assigning-egress-ips.html
https://examples.openshift.pub/networking/egress-ip/
https://www.openshift.com/blog/how-to-enable-static-egress-ip-in-ocp
www.openshift.com/blog/accessing-external-services-using-egress-router
Автор: Сергей Артемов, руководитель отдела DevOps-решений «Инфосистемы Джет»
===========
Источник:
habr.com
===========

Похожие новости: Теги для поиска: #_itinfrastruktura (IT-инфраструктура), #_devops, #_openshift, #_itinfrastruktura (ИТ-инфраструктура), #_open_shift, #_kontrol_trafika (контроль трафика), #_blog_kompanii_infosistemy_dzhet (
Блог компании Инфосистемы Джет
)
, #_itinfrastruktura (
IT-инфраструктура
)
, #_devops, #_openshift
Профиль  ЛС 
Показать сообщения:     

Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы

Текущее время: 22-Ноя 18:52
Часовой пояс: UTC + 5