Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!
В первой части статьи про OpenShift Egress мы рассмотрели варианты организации фиксированных исходящих IP-адресов для POD в кластере. Но что делать, если надо предоставить доступ во внешние по отношению к кластеру сегменты сети, находящиеся в определенных VLAN?
Манипуляции с IP-адресацией здесь не помогут. Единственным решением в этом случае будет организация дополнительных интерфейсов на узлах кластера, которые будут находиться в нужных VLAN, и организация доступа к дополнительным интерфейсам с нужных нам проектов внутри кластера. И помочь в этом может проект под названием Multus CNI.
Как известно, по умолчанию у POD в Kubernetes есть один интерфейс, через который и происходит все взаимодействие с ним. Multus позволяет создать в POD несколько интерфейсов помимо определенного по умолчанию. Фактически Multus сам является CNI-Plugin'ом, в свою очередь управляющий вызовом других CNI-Plugin'ов. За это Multus называют CNI meta Plugin. То, что делает Multus, хорошо показано на картинке из статьи Demystifing Multus:
Разумеется, количество дополнительных интерфейсов может быть больше чем один.
Итак, попробуем решить задачу доступа в выделенный VLAN на нашем стенде. По умолчанию всем узлам кластера выделен один интерфейс, находящийся в VLAN OpenShift (IP: 192.168.111/24). Мы хотим организовать доступ из проекта multes-test в ресурсы сети 192.168.112/24, находящейся в VLAN Restricted. VLAN Restricted и VLAN OpenShift между собой не маршрутизируются.
Для начала добавим на ряд узлов (в нашем случае это Node1 и Node2) интерфейс из VLAN Restricted, и поставим на этих узлах метку node-role.kubernetes.io/multus-node='yes'. C узлов с меткой multus-node будут доступны ресурсы из Restricted VLAN. Создадим наш проект multus-test:
Поддержка Multus CNI давно присутствует в OpenShift, отдельно добавлять ее не надо. Управление конфигурацией Multus производится через CR в CRD networks.operator.openshift.io. Необходимо отредактировать этот ресурс, добавив конфигурацию CNI Plugin для нового интерфейса:
oc edit networks.operator.openshift.io cluster
Этот момент требует расшифровки. Что мы определили данной конфигурацией?
Для нашего дополнительного интерфейса нужно выбрать используемый CNI Plugin. Список возможных CNI Plugin можно посмотреть на сайте www.cni.dev. В своем примере мы используем ipvlan plugin. По сути это простейший bridge, который позволяет контейнерам взаимодействовать через внешний сетевой интерфейс хоста. При этом все исходящие соединения используют свой IP-адрес, но будут иметь MAC-адрес внешнего сетевого интерфейса. Картинка с сайта hicu.be хорошо иллюстрирует работу ipvlan plugin:
В продуктивных окружениях чаще выбирают macvlan plugin, который отличается от ipvlan тем, что исходящие соединения имеют уникальные MAC-адреса. Но в этом случае зачастую необходима подготовка сетевой инфраструктуры, чтобы сетевое оборудование позволило передачу пакетов с разными MAC-адресами с одного порта.
Помимо организации сетевого интерфейса нам необходимо определить правила выдачи IP-адреса для нового интерфейса. Этим также занимается CNI Plugin, который реализует функции IP Address Management (или IPAM). Список возможных IPAM-plugin также можно посмотреть на сайте www.cni.dev. В данном примере мы использовали простейший static IPAM plugin, который присваивает фиксированный адрес нашему POD.
Если таких POD окажется много, использовать static IPAM станет неудобно. Хорошим выбором здесь будет либо использование dhcp plugin (он назначает IP адреса POD через запрос к внешнему DHCP-серверу), либо использование whereabouts plugin.
Поддержка этих IPAM Plugin также по умолчанию есть в OpenShift, отдельно устанавливать их не надо.
После определения нашей конфигурации Multus в кластере должен появиться ресурс под названием Network Attachment Definition, в котором отражена текущая конфигурация Multus:
Network Attachment Definition
Создадим тестовый POD с дополнительным интерфейсом, который будет иметь доступ в наш restricted VLAN:
pod-ipvlan-static.yaml
Зайдем в созданный POD, чтобы посмотреть его сетевую конфигурацию и проверить доступность адресов в restricted VLAN (в сети 192.168.112.0/24):
Как видно из вывода команды «ip a», POD получил дополнительный сетевой интерфейс net1@if826 и IP-адрес, который мы указали в его манифесте. Так как дополнительный интерфейс работает через ethernet адаптер, находящийся в restricted VLAN, с этого POD мы получили доступ в нужный нам сегмент сети.
Автор: Сергей Артемов, руководитель отдела DevOps-решений «Инфосистемы Джет»
Присоединяйтесь к нашему каналу в Telegram @DevSecOps Talks!
Манипуляции с IP-адресацией здесь не помогут. Единственным решением в этом случае будет организация дополнительных интерфейсов на узлах кластера, которые будут находиться в нужных VLAN, и организация доступа к дополнительным интерфейсам с нужных нам проектов внутри кластера. И помочь в этом может проект под названием Multus CNI.
Multus CNI
Как известно, по умолчанию у POD в Kubernetes есть один интерфейс, через который и происходит все взаимодействие с ним. Multus позволяет создать в POD несколько интерфейсов помимо определенного по умолчанию. Фактически Multus сам является CNI-Plugin'ом, в свою очередь управляющий вызовом других CNI-Plugin'ов. За это Multus называют CNI meta Plugin. То, что делает Multus, хорошо показано на картинке из статьи Demystifing Multus:
Разумеется, количество дополнительных интерфейсов может быть больше чем один.
Настройка Multus CNI в OpenShift
Итак, попробуем решить задачу доступа в выделенный VLAN на нашем стенде. По умолчанию всем узлам кластера выделен один интерфейс, находящийся в VLAN OpenShift (IP: 192.168.111/24). Мы хотим организовать доступ из проекта multes-test в ресурсы сети 192.168.112/24, находящейся в VLAN Restricted. VLAN Restricted и VLAN OpenShift между собой не маршрутизируются.
Для начала добавим на ряд узлов (в нашем случае это Node1 и Node2) интерфейс из VLAN Restricted, и поставим на этих узлах метку node-role.kubernetes.io/multus-node='yes'. C узлов с меткой multus-node будут доступны ресурсы из Restricted VLAN. Создадим наш проект multus-test:
[ocp@shift-is01 macvlan]$ oc new-project multus-test
Поддержка Multus CNI давно присутствует в OpenShift, отдельно добавлять ее не надо. Управление конфигурацией Multus производится через CR в CRD networks.operator.openshift.io. Необходимо отредактировать этот ресурс, добавив конфигурацию CNI Plugin для нового интерфейса:
oc edit networks.operator.openshift.io cluster
spec:
additionalNetworks:
- name : net1
namespace: multus-test
type: Raw
rawCNIConfig: |-
{ "cniVersion": "0.3.1",
"type": "ipvlan",
"mode": "l2",
"master": "ens224",
"ipam": {
"type": "static"
}
}
Этот момент требует расшифровки. Что мы определили данной конфигурацией?
- Для POD в проекте multus-test добавится интерфейс с названием «net1»
- Конфигурация этого интерфейса будет определяться через CNI Plugin «ipvlan»;
- CNI Plugin ipvlan сконфигурируется в L2 Mode;
- В качестве основного интерфейса для net1 используется физический интерфейс узла ens224;
- И, наконец, для управления IP-адресацией будет применяться IPAM static plugin.
Выбор CNI Plugin
Для нашего дополнительного интерфейса нужно выбрать используемый CNI Plugin. Список возможных CNI Plugin можно посмотреть на сайте www.cni.dev. В своем примере мы используем ipvlan plugin. По сути это простейший bridge, который позволяет контейнерам взаимодействовать через внешний сетевой интерфейс хоста. При этом все исходящие соединения используют свой IP-адрес, но будут иметь MAC-адрес внешнего сетевого интерфейса. Картинка с сайта hicu.be хорошо иллюстрирует работу ipvlan plugin:
В продуктивных окружениях чаще выбирают macvlan plugin, который отличается от ipvlan тем, что исходящие соединения имеют уникальные MAC-адреса. Но в этом случае зачастую необходима подготовка сетевой инфраструктуры, чтобы сетевое оборудование позволило передачу пакетов с разными MAC-адресами с одного порта.
Выбор IPAM Plugin
Помимо организации сетевого интерфейса нам необходимо определить правила выдачи IP-адреса для нового интерфейса. Этим также занимается CNI Plugin, который реализует функции IP Address Management (или IPAM). Список возможных IPAM-plugin также можно посмотреть на сайте www.cni.dev. В данном примере мы использовали простейший static IPAM plugin, который присваивает фиксированный адрес нашему POD.
Если таких POD окажется много, использовать static IPAM станет неудобно. Хорошим выбором здесь будет либо использование dhcp plugin (он назначает IP адреса POD через запрос к внешнему DHCP-серверу), либо использование whereabouts plugin.
Поддержка этих IPAM Plugin также по умолчанию есть в OpenShift, отдельно устанавливать их не надо.
Доступ в restricted VLAN
После определения нашей конфигурации Multus в кластере должен появиться ресурс под названием Network Attachment Definition, в котором отражена текущая конфигурация Multus:
Network Attachment Definition
[ocp@shift-is01 macvlan]$ oc get network-attachment-definitions --all-namespaces
NAMESPACE NAME AGE
multus-test net1 3m4s
[ocp@shift-is01 macvlan]$ oc get network-attachment-definitions.k8s.cni.cncf.io -n multus-test net1 -o yaml
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
creationTimestamp: "2020-11-02T16:44:46Z"
generation: 1
managedFields:
- apiVersion: k8s.cni.cncf.io/v1
fieldsType: FieldsV1
fieldsV1:
f:metadata:
f:ownerReferences:
.: {}
k:{"uid":"01a4f46a-fc3c-495f-b196-b39352421e2a"}:
.: {}
f:apiVersion: {}
f:blockOwnerDeletion: {}
f:controller: {}
f:kind: {}
f:name: {}
f:uid: {}
f:spec:
.: {}
f:config: {}
manager: cluster-network-operator
operation: Update
time: "2020-11-02T16:44:46Z"
name: net1
namespace: multus-test
ownerReferences:
- apiVersion: operator.openshift.io/v1
blockOwnerDeletion: true
controller: true
kind: Network
name: cluster
uid: 01a4f46a-fc3c-495f-b196-b39352421e2a
resourceVersion: "25898949"
selfLink: /apis/k8s.cni.cncf.io/v1/namespaces/multus-test/network-attachment-definitions/net1
uid: 7a7d718b-82c5-46fe-8f72-8fd4299508ec
spec:
config: |-
{ "cniVersion": "0.3.1",
"type": "ipvlan",
"mode": "l2",
"master": "ens224",
"ipam": {
"type": "static"
}
}
Создадим тестовый POD с дополнительным интерфейсом, который будет иметь доступ в наш restricted VLAN:
pod-ipvlan-static.yaml
[ocp@shift-is01 ipvlan]$ cat ./pod-ipvlan-static.yaml
apiVersion: v1
kind: Pod
metadata:
namespace: multus-test
name: test-multus-pod
labels:
app: test-multus-pod
annotations:
k8s.v1.cni.cncf.io/networks: '[
{
"name": "net1",
"ips": ["192.168.112.250/24"]
}
]'
spec:
nodeSelector:
node-role.kubernetes.io/multus-node: yes
containers:
- name: test-multus-pod
image: centos/tools
command: ["/bin/bash", "-c", "sleep 9000000"]
Зайдем в созданный POD, чтобы посмотреть его сетевую конфигурацию и проверить доступность адресов в restricted VLAN (в сети 192.168.112.0/24):
ocp@shift-is01 ipvlan]$ oc rsh test-multus-pod
sh-4.2# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
3: eth0@if2142: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UP group default
link/ether 0a:58:0a:fe:04:a0 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.254.4.160/24 brd 10.254.4.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::bc4b:abff:fe0b:91f8/64 scope link
valid_lft forever preferred_lft forever
4: net1@if826: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UNKNOWN group default
link/ether 00:50:56:96:f3:02 brd ff:ff:ff:ff:ff:ff
inet 192.168.112.250/24 brd 192.168.112.255 scope global net1
valid_lft forever preferred_lft forever
inet6 fe80::50:5600:196:f302/64 scope link
valid_lft forever preferred_lft forever
sh-4.2# ping 192.168.112.1 -c 3
PING 192.168.112.1 (192.168.112.1) 56(84) bytes of data.
64 bytes from 192.168.112.1: icmp_seq=1 ttl=64 time=0.179 ms
64 bytes from 192.168.112.1: icmp_seq=2 ttl=64 time=0.230 ms
64 bytes from 192.168.112.1: icmp_seq=3 ttl=64 time=0.223 ms
--- 192.168.112.1 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 2041ms
rtt min/avg/max/mdev = 0.179/0.210/0.230/0.028 ms
Как видно из вывода команды «ip a», POD получил дополнительный сетевой интерфейс net1@if826 и IP-адрес, который мы указали в его манифесте. Так как дополнительный интерфейс работает через ethernet адаптер, находящийся в restricted VLAN, с этого POD мы получили доступ в нужный нам сегмент сети.
Автор: Сергей Артемов, руководитель отдела DevOps-решений «Инфосистемы Джет»
Присоединяйтесь к нашему каналу в Telegram @DevSecOps Talks!
Список литературы
- OpenShift 4 with MacVLAN and whereabouts
- Demystifying Multus
- Macvlan vs Ipvlan