Все об OpenShift Egress. Часть 2

    В первой части статьи про OpenShift Egress мы рассмотрели варианты организации фиксированных исходящих IP-адресов для POD в кластере. Но что делать, если надо предоставить доступ во внешние по отношению к кластеру сегменты сети, находящиеся в определенных VLAN?


    Манипуляции с 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"
               }
            }
    

    Этот момент требует расшифровки. Что мы определили данной конфигурацией?

    1. Для POD в проекте multus-test добавится интерфейс с названием «net1»
    2. Конфигурация этого интерфейса будет определяться через CNI Plugin «ipvlan»;
    3. CNI Plugin ipvlan сконфигурируется в L2 Mode;
    4. В качестве основного интерфейса для net1 используется физический интерфейс узла ens224;
    5. И, наконец, для управления 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!

    Список литературы


    1. OpenShift 4 with MacVLAN and whereabouts
    2. Demystifying Multus
    3. Macvlan vs Ipvlan
    Инфосистемы Джет
    Системный интегратор

    Похожие публикации

    Комментарии 0

    Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

    Самое читаемое