Як pod у Kubernetes атрымлівае IP-адрас

Заўв. перав.: гэты артыкул, напісаны SRE-інжынерам з LinkedIn, у дэталях распавядае пра тую «ўнутраную магію» ў Kubernetes — дакладней, узаемадзеянне CRI, CNI і kube-apiserver, — што адбываецца, калі чарговаму pod'у патрабуецца прызначыць IP-адрас.

Адно з базавых патрабаванняў сеткавай мадэлі Kubernetes складаецца ў тым, што ў кожнага pod'а павінен быць свой уласны IP-адрас і любы іншы pod у кластары павінен мець магчымасць звязацца з ім па гэтым адрасе. Ёсць мноства сеткавых "правайдэраў" (Flannel, Calico, Canal і да т.п.), якія дапамагаюць рэалізаваць дадзеную сеткавую мадэль.

Калі я толькі пачынаў працаваць з Kubernetes, мне было не зусім ясна, як менавіта pod'ы атрымліваюць свае IP-адрасы. Нават з разуменнем, як функцыянуюць асобныя кампаненты, было складана ўявіць іх сумесную працу. Напрыклад, я ведаў, для чаго патрэбныя плагіны CNI, але не ўяўляў, як менавіта яны выклікаюцца. Таму вырашыў напісаць гэты артыкул, каб падзяліцца ведамі аб розных сеткавых кампанентах і іх сумеснай працы ў кластары Kubernetes, якія і дазваляюць кожнаму pod'у атрымаць свой унікальны IP-адрас.

Існуюць розныя спосабы арганізацыі сеткавага ўзаемадзеяння ў Kubernetes – аналагічна таму, як і розныя варыянты выкананых асяроддзяў (runtime) для кантэйнераў. У гэтай публікацыі будзе выкарыстоўвацца фланель для арганізацыі сеткі ў кластары, а ў якасці выкананага асяроддзя - Кантэйнер. Таксама я зыходжу са здагадкі, што вы ведаеце, як уладкована сеткавае ўзаемадзеянне паміж кантэйнерамі, таму толькі сцісла закрану яго, выключна для кантэксту.

Некаторыя базавыя паняцці

Кантэйнеры і сетка: кароткі агляд

У інтэрнэце дастаткова выдатных публікацый, якія тлумачаць, як кантэйнеры звязваюцца адзін з адным па сетцы. Таму правяду толькі агульны агляд асноўных паняццяў і абмяжуюся адным падыходам, які разумее стварэнне Linux-моста і інкапсуляцыю пакетаў. Падрабязнасці апушчаны, паколькі сама тэма сеткавага ўзаемадзеяння кантэйнераў заслугоўвае асобнага артыкула. Спасылкі на некаторыя асабліва змястоўныя і пазнавальныя публікацыі будуць прыведзены ніжэй.

Кантэйнеры на адным хасце

Адзін з спосабаў арганізацыі сувязі па IP-адрасам паміж кантэйнерамі, якія працуюць на адным і тым жа хасце, мяркуе стварэнне Linux-моста. Для гэтага ў Kubernetes (і Docker) ствараюцца віртуальныя прылады veth (virtual 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-адрас, важна пераканацца ў тым, каб гэты адрас быў унікальным. Гэта дасягаецца шляхам вылучэння кожнаму вузлу ўнікальнай падсеткі, з якой затым pod'ам на гэтым вузле прызначаюцца IP-адрасы.

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

Калі nodeipam перадаецца ў якасці параметра сцяга --controllers kube-controller-manager'а, ён кожнаму вузлу вылучае асобную падсетку (podCIDR) з CIDR кластара (г.зн. дыяпазону IP-адрасоў для сеткі кластара). Паколькі гэтыя podCIDR'ы не перасякаюцца, становіцца магчымым кожнаму pod'у вылучыць унікальны IP-адрас.

Вузлу Kubernetes прысвойваецца podCIDR у момант яго пачатковай рэгістрацыі ў кластары. Каб змяніць podCIDR у вузлоў, неабходна іх дэрэгістраваць і затым паўторна зарэгістраваць, у прамежку занясучы адпаведныя змены ў канфігурацыю кіраўніка пласта Kubernetes. Вывесці podCIDR вузла можна з дапамогай наступнай каманды:

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

Kubelet, серада запуску кантэйнера і плагіны CNI: як гэта ўсё працуе

Планаванне pod'а на вузел злучана з выкананнем мноства падрыхтоўчых дзеянняў. У гэтым раздзеле я сканцэнтруюся толькі на тых з іх, якія непасрэдна злучаны з наладай сеткі pod'а.

Планаванне pod'а на нейкі вузел запускае наступны ланцужок падзей:

Як pod у Kubernetes атрымлівае IP-адрас

Даведка: Архітэктура CRI-плагінаў Containerd.

Узаемадзеянне асяроддзя запуску кантэйнераў і плагінаў CNI

У кожнага сеткавага правайдэра маецца свая ўбудова CNI. Runtime кантэйнера запускае яго, каб сканфігураваць сетку для pod'a у працэсе яго запуску. У выпадку 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 у якасці init-кантэйнера.
  • Install-cni стварае файл канфігурацыі CNI (/etc/cni/net.d/10-flannel.conflist) на кожным вузле.
  • Flanneld стварае прыладу vxlan, здабывае сеткавыя метададзеныя з API-сервера і сочыць за абнаўленнямі pod'аў. Па меры іх стварэння ён распаўсюджвае маршруты для ўсіх pod'аў па ўсім кластары.
  • Гэтыя маршруты і дазваляюць pod'ам звязвацца сябар з сябрам па IP-адрасам.

Для атрымання больш падрабязнай інфармацыі аб рабоце Flannel рэкамендую скарыстацца спасылкамі ў канцы артыкула.

Вось схема ўзаемадзеяння паміж убудовай Containerd CRI і ўбудовамі CNI:

Як pod у Kubernetes атрымлівае IP-адрас

Як відаць вышэй, kubelet выклікае плягін Containerd CRI, каб стварыць pod, а той ужо выклікае плягін CNI для налады сеткі pod'а. Пры гэтым 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», Што паказваецца ў канфігу. Затым для кожнага pod'а ствараецца пара 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"
  }
}

Host-local IPAM-плягін (IP Aдрас Management - кіраванне IP-адрасамі) вяртае IP-адрас для кантэйнера з падсеткі і захоўвае выдзелены IP на хасце ў дырэкторыі, указанай у раздзеле dataDir - /var/lib/cni/networks/<network-name=cni0>/<ip>. У гэтым файле ўтрымоўваецца ID кантэйнера, якому прысвоены дадзены IP-адрас.

Пры выкліку host-local 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 ці па адрасе [электронная пошта абаронена]. Не саромейцеся звяртацца, калі захочаце абмеркаваць аспекты гэтага артыкула ці што-небудзь іншае. Я з задавальненнем пагутару з вамі!

Спасылкі

Кантэйнеры і сетка

Як працуе Flannel

CRI і CNI

PS ад перакладчыка

Чытайце таксама ў нашым блогу:

Крыніца: habr.com

Дадаць каментар