В 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 имеет следующую сетевую конфигурацию:
Первым шагом необходимо настроить 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.