Как pod в Kubernetes получава IP адрес

Прим. прев.: тази статия, написана от SRE инженер в LinkedIn, детайлно описва онези „вътрешни магии“ в Kubernetes — по-точно, взаимодействието между CRI, CNI и kube-apiserver, — което се случва, когато на даден pod му е нужен IP адрес.

Едно от основните изисквания на мрежовата модел на Kubernetes е, че всеки pod трябва да има собствен IP адрес и всеки друг pod в кластера трябва да може да се свърже с него по този адрес. Съществуват много мрежови „доставчици“ (Flannel, Calico, Canal и т.н.), които помагат за изпълнението на тази мрежова модел.

Когато току-що започвах да работя с Kubernetes, не ми беше съвсем ясно как подовете получават своите IP адреси. Дори след като разбрах как функционират отделните компоненти, беше трудно да си представя тяхното съвместно действие. Например, знаех за какво служат CNI плъгините, но не знаех как точно се извикват. Затова реших да напиша тази статия, за да споделя знанията си за различните мрежови компоненти и тяхната съвместна работа в кластера на Kubernetes, които позволяват на всеки pod да получи уникален IP адрес.

Съществуват различни начини за организиране на мрежовото взаимодействие в Kubernetes — подобно на различните варианти на изпълнителни среди (runtime) за контейнери. В това публикуване ще се използва Flannel за организиране на мрежата в кластера, а като изпълнителна среда — Containerd. Също така предполагам, че знаете как функционира мрежовото взаимодействие между контейнерите, затова ще засегна темата само накратко, единствено за контекст.

Някои основни понятия

Контейнери и мрежа: кратък обзор

В интернет има много отлични статии, които обясняват как контейнерите се свързват помежду си по мрежата. Затова ще направя само общ преглед на основните понятия и ще се огранича до един подход, свързан със създаването на Linux мост и инкапсулацията на пакети. Подробностите са опуснати, тъй като самата тема за мрежовото взаимодействие на контейнерите заслужава отделна статия. По-долу ще бъдат предоставени връзки към някои особено съдържателни и познавателни публикации.

Контейнери на един хост

Един от начините за организиране на свързаност по IP адреси между контейнери, работещи на един и същи хост, предвижда създаването на Linux мост. За целта в Kubernetes (и Docker) се създават виртуални устройства veth (виртуален Ethernet). Единият край на veth устройството е свързан към мрежовото пространство на името на контейнера, а другият — към Linux моста в мрежата на хоста.

Всички контейнери на един хост имат един от краищата на veth, свързан към моста, чрез който те могат да комуникират помежду си по IP адреси. Linux мостът също има IP адрес и служи като шлюз за изходящия (egress) трафик от pod-овете, предназначен за други възли.

Как pod в Kubernetes получава IP адрес

Контейнери на различни хостове

Инкапсулацията на пакети е един от начините, позволяващи на контейнерите на различни възли да комуникират помежду си по IP адреси. В Flannel за тази функция отговаря технологията vxlan, която "опакова" оригиналния пакет в UDP пакет и след това го изпраща на адреса.

В кластера Kubernetes Flannel създава устройство vxlan и съответно допълва таблицата за маршрути на всеки от възлите. Всеки пакет, предназначен за контейнер на друг хост, преминава през устройството vxlan и се инкапсулира в UDP пакет. На целта вложеният пакет се извлича и пренасочва към необходимия pod.

Как pod в Kubernetes получава IP адрес
Забележка: Това е само един от начините за организиране на мрежовото взаимодействие между контейнерите.

Какво е CRI?

CRI (Container Runtime Interface) е плъгин, който позволява на kubelet да използва различни изпълними среди на контейнери. API CRI е вграден в различни изпълними среди, така че потребителите могат да избират runtime по собствено усмотрение.

Какво е CNI?

Проект CNI представлява спецификацията за организиране на универсално мрежово решение за Linux контейнери. Освен това, той включва плъгини, отговарящи за различни функции при настройка на мрежата на pod-а. Плъгинът CNI е изпълним файл, който съответства на спецификацията (някои плъгини ще обсъдим по-долу).

Разпределение на подсетите на възлите за назначаване на IP адреси на pod-овете

Тъй като всеки pod в клъстера трябва да има IP адрес, е важно да се уверите, че този адрес е уникален. Това се постига чрез разпределяне на уникална подсетка на всеки възел, от която след това се назначават IP адреси на pod-овете на този възел.

Контролерът IPAM на възела

Когато nodeipam се предава като параметър на флага --controllers на kube-controller-manager-a, той разпределя индивидуален подмрежов адрес (podCIDR) на всеки възел (т.е. диапазон IP адреси за мрежата на клъстера). Тъй като тези podCIDR не се припокриват, става възможно да се назначи уникален IP адрес на всеки pod.

На възел в Kubernetes се назначава podCIDR по време на първоначалната му регистрация в клъстера. За да промените podCIDR на възлите, е необходимо да ги дерегирате и след това да ги регистрирате отново, като в интервала извършите съответните промени в конфигурацията на управляващия слой на Kubernetes. Можете да извлечете podCIDR на възел с помощта на следната команда:

$ kubectl get no  -o json | jq '.spec.podCIDR'
10.244.0.0/24

Kubelet, среда за стартиране на контейнери и CNI плъгини: как всичко това работи

Планирането на pod на възел е свързано с изпълнението на множество подготовителни действия. В този раздел ще се съсредоточа само върху тези от тях, които са пряко свързани с конфигурирането на мрежата на pod.

Планирането на pod на определен възел задейства следната верига от събития:

Как pod в Kubernetes получава IP адрес

Помощ: Архитектура на CRI плъгините Containerd.

Взаимодействие между средата за стартиране на контейнери и CNI плъгините

Всеки мрежов доставчик има свой CNI плъгин. Средата за стартиране на контейнера го стартира, за да конфигурира мрежата за pod по време на неговото стартиране. В случай на containerd, стартирането на CNI плъгина се извършва от плъгина Containerd CRI.

Всеки доставчик има свой агент. Той се инсталира на всички възли в Kubernetes и отговаря за мрежовата конфигурация на pod. Този агент идва или с конфигурацията на CNI, или самостоятелно я създава на възела. Конфигурацията помага на CRI плъгина да установи кой CNI плъгин да извиква.

Местоположението на CNI конфигурацията може да бъде настроено; по подразбиране тя се намира в /etc/cni/net.d/<config-file>. Администраторите на клъстера също отговарят за инсталирането на CNI плъгините на всеки възел в клъстера. Местоположението им също може да бъде настроено; директорията по подразбиране е /opt/cni/bin.

При използване на containerd пътищата за конфигурацията и бинарниците на плъгина могат да бъдат зададени в секцията [plugins."io.containerd.grpc.v1.cri".cni] в в конфигурационния файл на containerd.

Тъй като използваме Flannel като мрежов доставчик, нека поговорим малко за неговата конфигурация:

  • Flanneld (демон на Flannel) обикновено се инсталира в клъстера като DaemonSet с install-cni в качеството на инициализиращ контейнер.
  • Install-cni създава файл с CNI конфигурация (/etc/cni/net.d/10-flannel.conflist) на всеки възел.
  • Flanneld създава vxlan устройство, извлича мрежови метаданни от API сървъра и следи за обновленията на подовете. Със създаването им той разпространява маршрути за всички подове из целия клъстер.
  • Тези маршрути позволяват на подовете да се свързват помежду си по IP адреси.

За повече информация относно работата на Flannel, препоръчвам да се запознаете с линковете в края на статията.

Ето схемата на взаимодействие между плъгина Containerd CRI и плъгините CNI:

Как pod в Kubernetes получава IP адрес

Както се вижда по-горе, kubelet извиква плъгина Containerd CRI, за да създаде под, а той от своя страна извиква плъгина CNI за настройка на мрежата на пода. В този процес CNI плъгинът на мрежовия доставчик извиква други основни CNI плъгини за настройка на различни аспекти на мрежата.

Взаимодействие между CNI плъгини

Съществуват различни CNI плъгини, чиято задача е да подпомагат настройването на мрежовото взаимодействие между контейнерите на хоста. В тази статия ще говорим за три от тях.

CNI плъгин Flannel

При използването на Flannel като мрежов доставчик, компонентът Containerd CRI извиква CNI плъгин Flannel, използвайки конфигурационния файл CNI /etc/cni/net.d/10-flannel.conflist.

$ cat /etc/cni/net.d/10-flannel.conflist
{
  "name": "cni0",
  "plugins": [
    {
      "type": "flannel",
      "delegate": {
         "ipMasq": false,
        "hairpinMode": true,
        "isDefaultGateway": true
      }
    }
  ]
}

CNI плъгин Flannel работи съвместно с Flanneld. По време на стартиране Flanneld извлича podCIDR и други свързани с мрежата подробности от API сървъра и ги записва в файл /run/flannel/subnet.env.

FLANNEL_NETWORK=10.244.0.0/16 
FLANNEL_SUBNET=10.244.0.1/24
FLANNEL_MTU=1450 
FLANNEL_IPMASQ=false

CNI плъгин Flannel използва данни от /run/flannel/subnet.env за настройка и извикване на CNI плъгина на моста (bridge).

CNI плъгин Bridge

Този плъгин се извиква с следната конфигурация:

{
  "name": "cni0",
  "type": "bridge",
  "mtu": 1450,
  "ipMasq": false,
  "isGateway": true,
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24"
  }
}

При първото извикване той създава Linux мост с "name": "cni0", който се посочва в конфигурацията. След това за всеки под се създава двойка veth. Единият край се свързва с пространството за мрежа на контейнера, а другият влиза в Linux моста в мрежата на хоста. CNI плъгин Bridge свързва всички контейнери на хоста към Linux моста в мрежата на хоста.

След приключване с настройката на двойката veth, плъгинът Bridge извиква локалния за хоста (host-local) CNI плъгин IPAM. Типът на IPAM плъгина може да бъде настроен в конфигурацията CNI, която плъгинът CRI използва за извикване на CNI плъгина Flannel.

Локалните за хоста IPAM плъгини CNI

Bridge CNI извиква локалния IPAM плъгин на CNI с следната конфигурация:

{
  "name": "cni0",
  "ipam": {
    "type": "host-local",
    "subnet": "10.244.0.0/24",
    "dataDir": "/var/lib/cni/networks"
  }
}

IPAM плъгин на хост-локал (IP Aадрес Mуправление — управление IP адреси) върнал IP адрес за контейнер от подсет и запазва заделения IP на хоста в директорията, посочена в раздела dataDir — /var/lib/cni/networks/<network-name=cni0>/<ip>. В този файл се съдържа ID на контейнера, на който е присвоен този IP адрес.

При извикване на хост-локал IPAM-плъгина той връща следните данни:

{
  "ip4": {
    "ip": "10.244.4.2",
    "gateway": "10.244.4.3"
  },
  "dns": {}
}

Резюме

Kube-controller-manager присвоява podCIDR на всеки възел. Pod-ите на всеки възел получават IP адреси от адресното пространство в определен диапазон podCIDR. Понеже podCIDR-ите на възлите не се припокриват, всички pod-ове получават уникални IP адреси.

Администраторът на Kubernetes клъстера настройва и инсталира kubelet, средата за стартиране на контейнерите, агента на мрежовия доставчик и копира CNI плъгини на всеки възел. По време на стартиране агентът на мрежовия доставчик генерира CNI конфигурация. Когато pod-ът е планиран на възел, kubelet извиква CRI плъгина за неговото създаване. След това, ако се използва containerd, плъгинът Containerd CRI извиква CNI плъгина, посочен в CNI конфигурацията, за настройка на мрежата на pod-а. В резултат pod-ът получава IP адрес.

Отне ми известно време да разбера всички нюанси и детайли на тези взаимодействия. Надявам се придобитият опит да помогне и на вас да разберете по-добре как функционира Kubernetes. Ако греша в нещо, пожалуйста, свържете се с мен на Twitter или на адрес hello@ronaknathani.com. Не се колебайте да се свържете, ако искате да обсъдим аспектите на тази статия или нещо друго. Ще се радвам да поговоря с вас!

Връзки

Контейнери и мрежа

Как работи Flannel

CRI и CNI

P.S. от преводача

Прочетете също в нашия блог:

Източник: habr.com

Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри 🔥 Купете надежден хостинг за сайтове със защита от DDoS, VPS и VDS сървъри | ProHoster