Настраиваем сетевую связность внешнего узла с кластером Kubernetes | Паршин Павел

В Kubernetes есть два распространённых способа предоставления внешнего доступа к сервисам - используя ресурс Ingress или сервисы типа LoadBalancer. В большинстве случаев это наиболее простые и удобные способы, которые покрывают большую часть потребностей конечных пользователей. В отдельных случаях администратору кластера необходимо обеспечить сетевую связность кластера с остальной инфраструктурой проекта, например, для прямого доступа к подам или сервисам типа ClusterIP и NodePort вне кластера.

Kubernetes оставляет выбор реализации сетевой инфраструктуры пользователю, предоставляя множество плагинов CNI. Я буду использовать в этой статье проект Calico. Для других реализаций CNI детали могут отличаться, но сам подход должен быть похожим.

Calico создаёт маршрутизируемую сеть, в которой контейнеры представлены как обычные IP узлы. Вы можете общаться с ними с любого хоста в кластере (при условии наличия разрешений применяемой сетевой политики), используя их IP адреса. Для внешнего доступа к подам и сервисам узлы Calico могут обмениваться с доверенными узлами маршрутами по протоколу Border Gateway Protocol (BGP). BGP - это широко распространённый протокол обмена информацией между маршрутизаторами в сети. Каждый маршрутизатор может иметь один или более BGP пиров - другие маршрутизаторы, с которыми происходит обмен информацией по протоколу BGP. Calico запускает виртуальный BGP маршрутизатор на каждом узле кластера. Можно настроить узлы Calico для обмена данными друг с другом, с рефлектором маршрутов (route reflector) или с top-of-rack (ToR) маршрутизаторами (подробнее в документации).

Рассматриваемый кластер Kubernetes имеет следующую сетевую конфигурацию:

  • В качестве CNI используется Calico
  • IP адреса узлов аллоцируются из сети 172.34.8.0/24
  • IP адреса подов аллоцируются из сети 192.168.0.0/16
  • IP адреса сервисов аллоцируются из сети 10.96.0.0/12
  • Внешняя машина имеет IP адрес 172.34.8.45 (я создал машину в той же сети, что и узлы кластера, но это необязательно - главное иметь L2 связность).

Первым шагом необходимо настроить Bird Internet Routing Daemon (BIRD) на подключаемой машине. Для этого устанавливаем и конфигурируем BIRD, чтобы он мог обмениваться маршрутами с каждым узлом в сети Calico:

# Configure logging
log stderr all;

# This pseudo-protocol performs synchronization between BIRD's routing
# tables and the kernel. If your kernel supports multiple routing tables
# (as Linux 2.2.x does), you can run multiple instances of the kernel
# protocol and synchronize different kernel tables with different BIRD tables.
protocol kernel {
    persist; # Don't remove routes on bird shutdown
    scan time 20; # Scan kernel routing table every 20 seconds
    import none;
    export all;
    merge paths on; # Allow export multipath routes (ECMP)
}

# This pseudo-protocol watches all interface up/down events.
protocol device {
    scan time 10; # Scan interfaces every 10 seconds
}

template bgp kube_peer {
    # AS number можно выбрать произвольный согласно вашим требованиям.
    local as 65112;

    import all;
    export none;
}

protocol bgp peer from kube_peer {
    # С помощью range мы указываем CIDR сети узлов, чтобы не перечислять
    # каждый узел кластера по отдельности. Однако эта опция не поддерживается в старых версиях BIRD.
    # Здесь указывается AS сети Calico. По умолчанию 64512.
    neighbor range 172.34.8.0/24 as 64512;
}

После того как мы настроили получение маршрутов на машине, необходимо разрешить BGP пиринг на стороне Calico. С помощью следующего манифеста мы сообщаем Calico о внешнем маршрутизаторе:

calicoctl apply -f - << EOF
apiVersion: projectcalico.org/v3
kind: BGPPeer
metadata:
  name: bgppeer-external
spec:
  peerIP: 172.34.8.45
  asNumber: 65112
EOF

С настроенным пирингом Calico распространил маршруты к подам на внешнюю машину, делая поды доступными напрямую. Для обмена маршрутами сервисов нужно создать ресурс BGPConfiguration:

calicoctl create -f - <<EOF
apiVersion: projectcalico.org/v3
kind: BGPConfiguration
metadata:
  name: default
spec:
  serviceClusterIPs:
  - cidr: 10.96.0.0/12
EOF

Посмотрим на таблицу маршрутов после импорта маршрутов до подов и сервисов кластера на внешней машине:

ip r s
...
10.96.0.0/12 proto bird 
    nexthop via 172.34.8.10 dev eth0 weight 1 
    nexthop via 172.34.8.30 dev eth0 weight 1 
    nexthop via 172.34.8.76 dev eth0 weight 1 
    nexthop via 172.34.8.87 dev eth0 weight 1
192.168.204.0/26 proto bird 
    nexthop via 172.34.8.10 dev eth0 weight 1 
    nexthop via 172.34.8.30 dev eth0 weight 1 
    nexthop via 172.34.8.76 dev eth0 weight 1 
    nexthop via 172.34.8.87 dev eth0 weight 1
192.168.219.128/26 proto bird 
    nexthop via 172.34.8.10 dev eth0 weight 1 
    nexthop via 172.34.8.30 dev eth0 weight 1 
    nexthop via 172.34.8.76 dev eth0 weight 1 
    nexthop via 172.34.8.87 dev eth0 weight 1

Обратите внимание, что маршруты к подовой и сервисной сетям распределены по каждому узлу в кластере с помощью ECMP.

Если ваша инфраструктура построена поверх OpenStack, то необходимо каждому узлу кластера разрешить принимать сетевой трафик для подовой и сервисной сетей. По умолчанию такой трафик будет блокироваться. Для этого в настройках виртуальной машины добавьте CIDR сетей в список Allowed Address Pairs.

Предыдущая запись