- Регистрация
- 21.07.20
- Сообщения
- 40.408
- Реакции
- 1
- Репутация
- 0
Прим. перев.: эта статья, написанная SRE-инженером из LinkedIn, в деталях рассказывает о той «внутренней магии» в Kubernetes — точнее, взаимодействии CRI, CNI и kube-apiserver, — что происходит, когда очередному pod'у требуется назначить IP-адрес.
Одно из базовых требований
Когда я только начинал работать с Kubernetes, мне было не совсем ясно, как именно pod'ы получают свои IP-адреса. Даже с пониманием, как функционируют отдельные компоненты, было сложно представить их совместную работу. Например, я знал, для чего нужны плагины CNI, но не представлял, как именно они вызываются. Поэтому решил написать эту статью, чтобы поделиться знаниями о различных сетевых компонентах и их совместной работе в кластере Kubernetes, которая и позволяет каждому pod'у получить свой уникальный IP-адрес.
Существуют различные способы организации сетевого взаимодействия в Kubernetes — аналогично тому, как и различные варианты исполняемых сред (runtime) для контейнеров. В этой публикации будет использоваться
Некоторые базовые понятия
Контейнеры и сеть: краткий обзор
В интернете достаточно отличных публикаций, объясняющих, как контейнеры связываются друг с другом по сети. Поэтому проведу лишь общий обзор основных понятий и ограничусь одним подходом, подразумевающим создание Linux-моста и инкапсуляцию пакетов. Подробности опущены, поскольку сама тема сетевого взаимодействия контейнеров заслуживает отдельной статьи. Ссылки на некоторые особенно содержательные и познавательные публикации будут приведены ниже.
Контейнеры на одном хосте
Один из способов организации связи по IP-адресам между контейнерами, работающими на одном и том же хосте, предполагает создание Linux-моста. Для этого в Kubernetes (и Docker) создаются виртуальные устройства
У всех контейнеров на одном хосте один из концов veth подключен к мосту, через который они могут связываться друг с другом по IP-адресам. У Linux-моста также имеется IP-адрес, и он выступает в качестве шлюза для исходящего (egress) трафика из pod'ов, предназначенного для других узлов.
Контейнеры на разных хостах
Инкапсуляция пакетов — один из способов, позволяющий контейнерам на разных узлах связываться друг с другом по IP-адресам. Во Flannel за эту возможность отвечает технология
В кластере Kubernetes Flannel создает устройство vxlan и соответствующим образом дополняет таблицу маршрутов на каждом из узлов. Каждый пакет, предназначенный для контейнера на другом хосте, проходит через устройство vxlan и инкапсулируется в пакет UDP. В пункте назначения вложенный пакет извлекается и перенаправляется на нужный pod.
Примечание: Это лишь один из способов организации сетевого взаимодействия между контейнерами.
Что такое CRI?
Что такое CNI?
Выделение подсетей узлам для назначения IP-адресов pod'ам
Поскольку каждый pod кластера должен иметь IP-адрес, важно убедиться в том, чтобы этот адрес был уникальным. Это достигается путем выделения каждому узлу уникальной подсети, из которой затем pod'ам на этом узле назначаются IP-адреса.
Контроллер IPAM узла
Когда nodeipam передается в качестве параметра флага --controllers
Узлу Kubernetes присваивается podCIDR в момент его начальной регистрации в кластере. Чтобы изменить podCIDR у узлов, необходимо их дерегистрировать и затем повторно зарегистрировать, в промежутке внеся соответствующие изменения в конфигурацию управляющего слоя Kubernetes. Вывести podCIDR узла можно с помощью следующей команды:
$ kubectl get no -o json | jq '.spec.podCIDR'
10.244.0.0/24
Kubelet, среда запуска контейнера и плагины CNI: как это все работает
Планирование pod'а на узел связано с выполнением множества подготовительных действий. В этом разделе я сконцентрируюсь только на тех из них, которые непосредственно связаны с настройкой сети pod'а.
Планирование pod'а на некий узел запускает следующую цепочку событий:
Справка:
Взаимодействие среды запуска контейнеров и плагинов CNI
У каждого сетевого провадера имеется свой плагин CNI. Runtime контейнера запускает его, чтобы сконфигурировать сеть для pod'a в процессе его запуска. В случае containerd запуском CNI-плагина занимается плагин
При этом у каждого провайдера есть свой агент. Он устанавливается во все узлы Kubernetes и отвечает за сетевую настройку pod'ов. Этот агент идет либо в комплекте с конфигом CNI, либо самостоятельно создает его на узле. Конфиг помогает CRI-плагину установить, какой плагин CNI вызывать.
Местонахождение конфига CNI можно настроить; по умолчанию он лежит в /etc/cni/net.d/. Администраторы кластера также отвечают за установку плагинов CNI на каждый узел кластера. Их местонахождение также настраивается; директория по умолчанию — /opt/cni/bin.
При использовании containerd пути для конфига и бинарников плагина можно задать в разделе [plugins.«io.containerd.grpc.v1.cri».cni] в
Поскольку мы используем Flannel в качестве сетевого провайдера, давайте немного поговорим о его настройке:
Для получения более подробной информации о работе Flannel рекомендую воспользоваться ссылками в конце статьи.
Вот схема взаимодействия между плагином Containerd CRI и плагинами CNI:
Как видно выше, kubelet вызывает плагин Containerd CRI, чтобы создать pod, а тот уже вызывает плагин CNI для настройки сети pod'а. При этом CNI-плагин сетевого провайдера вызывает другие базовые плагины CNI для настройки различных аспектов сети.
Взаимодействие между CNI-плагинами
Существуют различные плагины CNI, задача которых — помочь настроить сетевое взаимодействие между контейнерами на хосте. В этой статье речь пойдет о трех из них.
CNI-плагин Flannel
При использовании Flannel в качестве сетевого провайдера компонент Containerd CRI вызывает
$ 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-мост в сети хоста.
Закончив с настройкой пары veth, плагин Bridge вызывает локальный для хоста (host-local) CNI-плагин IPAM. Тип IPAM-плагина можно настроить в конфиге CNI, который плагин CRI использует для вызова CNI-плагина Flannel.
Локальные для хоста IPAM-плагины CNI
Bridge CNI вызывает
{
"name": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24",
"dataDir": "/var/lib/cni/networks"
}
}
Host-local IPAM-плагин (IP Address Management — управление IP-адресами) возвращает IP-адрес для контейнера из подсети и сохраняет выделенный IP на хосте в директории, указанной в разделе dataDir — /var/lib/cni/networks//. В этом файле содержится 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. Если я в чем-то ошибаюсь, пожалуйста, свяжитесь со мной в
Ссылки
Контейнеры и сеть
Как работает Flannel
CRI и CNI
P.S. от переводчика
Читайте также в нашем блоге:
Одно из базовых требований
You must be registered for see links
состоит в том, что у каждого pod'а должен быть свой собственный IP-адрес и любой другой pod в кластере должен иметь возможность связаться с ним по этому адресу. Есть множество сетевых «провайдеров» (Flannel, Calico, Canal и т.п.), которые помогают реализовать данную сетевую модель.Когда я только начинал работать с Kubernetes, мне было не совсем ясно, как именно pod'ы получают свои IP-адреса. Даже с пониманием, как функционируют отдельные компоненты, было сложно представить их совместную работу. Например, я знал, для чего нужны плагины CNI, но не представлял, как именно они вызываются. Поэтому решил написать эту статью, чтобы поделиться знаниями о различных сетевых компонентах и их совместной работе в кластере Kubernetes, которая и позволяет каждому pod'у получить свой уникальный IP-адрес.
Существуют различные способы организации сетевого взаимодействия в Kubernetes — аналогично тому, как и различные варианты исполняемых сред (runtime) для контейнеров. В этой публикации будет использоваться
You must be registered for see links
для организации сети в кластере, а в качестве исполняемой среды —
You must be registered for see links
. Также я исхожу из предположения, что вы знаете, как устроено сетевое взаимодействие между контейнерами, поэтому лишь вкратце затрону его, исключительно для контекста.Некоторые базовые понятия
Контейнеры и сеть: краткий обзор
В интернете достаточно отличных публикаций, объясняющих, как контейнеры связываются друг с другом по сети. Поэтому проведу лишь общий обзор основных понятий и ограничусь одним подходом, подразумевающим создание Linux-моста и инкапсуляцию пакетов. Подробности опущены, поскольку сама тема сетевого взаимодействия контейнеров заслуживает отдельной статьи. Ссылки на некоторые особенно содержательные и познавательные публикации будут приведены ниже.
Контейнеры на одном хосте
Один из способов организации связи по IP-адресам между контейнерами, работающими на одном и том же хосте, предполагает создание Linux-моста. Для этого в Kubernetes (и Docker) создаются виртуальные устройства
You must be registered for see links
. Один конец veth-устройства подключается к сетевому пространству имен контейнера, другой — к
You must be registered for see links
в сети хоста.У всех контейнеров на одном хосте один из концов veth подключен к мосту, через который они могут связываться друг с другом по IP-адресам. У Linux-моста также имеется IP-адрес, и он выступает в качестве шлюза для исходящего (egress) трафика из pod'ов, предназначенного для других узлов.
Контейнеры на разных хостах
Инкапсуляция пакетов — один из способов, позволяющий контейнерам на разных узлах связываться друг с другом по IP-адресам. Во Flannel за эту возможность отвечает технология
You must be registered for see links
, которая «упаковывает» исходный пакет в пакет UDP и затем отправляет его по назначению.В кластере Kubernetes Flannel создает устройство vxlan и соответствующим образом дополняет таблицу маршрутов на каждом из узлов. Каждый пакет, предназначенный для контейнера на другом хосте, проходит через устройство vxlan и инкапсулируется в пакет UDP. В пункте назначения вложенный пакет извлекается и перенаправляется на нужный pod.
Примечание: Это лишь один из способов организации сетевого взаимодействия между контейнерами.
Что такое CRI?
You must be registered for see links
— это плагин, позволяющий kubelet'у использовать разные исполняемые среды контейнеров. API CRI встроен в различные исполняемые среды, поэтому пользователи могут выбирать runtime по своему усмотрению.Что такое CNI?
You must be registered for see links
представляет собой
You must be registered for see links
для организации универсального сетевого решения для Linux-контейнеров. Кроме того, он включает в себя
You must be registered for see links
, отвечающие за различные функции при настройке сети pod'а. Плагин CNI — это исполняемый файл, соответствующи спецификации (некоторые плагины мы обсудим ниже).Выделение подсетей узлам для назначения IP-адресов pod'ам
Поскольку каждый pod кластера должен иметь IP-адрес, важно убедиться в том, чтобы этот адрес был уникальным. Это достигается путем выделения каждому узлу уникальной подсети, из которой затем pod'ам на этом узле назначаются IP-адреса.
Контроллер IPAM узла
Когда nodeipam передается в качестве параметра флага --controllers
You must be registered for see links
, он каждому pod'у выделяет отдельную подсеть (podCIDR) из CIDR кластера (т.е. диапазона IP-адресов для сети кластера). Поскольку эти podCIDR'ы не пересекаются, становится возможным каждому pod'у выделить уникальный IP-адрес.Узлу Kubernetes присваивается podCIDR в момент его начальной регистрации в кластере. Чтобы изменить podCIDR у узлов, необходимо их дерегистрировать и затем повторно зарегистрировать, в промежутке внеся соответствующие изменения в конфигурацию управляющего слоя Kubernetes. Вывести podCIDR узла можно с помощью следующей команды:
$ kubectl get no -o json | jq '.spec.podCIDR'
10.244.0.0/24
Kubelet, среда запуска контейнера и плагины CNI: как это все работает
Планирование pod'а на узел связано с выполнением множества подготовительных действий. В этом разделе я сконцентрируюсь только на тех из них, которые непосредственно связаны с настройкой сети pod'а.
Планирование pod'а на некий узел запускает следующую цепочку событий:
Справка:
You must be registered for see links
.Взаимодействие среды запуска контейнеров и плагинов CNI
У каждого сетевого провадера имеется свой плагин CNI. Runtime контейнера запускает его, чтобы сконфигурировать сеть для pod'a в процессе его запуска. В случае containerd запуском CNI-плагина занимается плагин
You must be registered for see links
.При этом у каждого провайдера есть свой агент. Он устанавливается во все узлы Kubernetes и отвечает за сетевую настройку pod'ов. Этот агент идет либо в комплекте с конфигом CNI, либо самостоятельно создает его на узле. Конфиг помогает CRI-плагину установить, какой плагин CNI вызывать.
Местонахождение конфига CNI можно настроить; по умолчанию он лежит в /etc/cni/net.d/. Администраторы кластера также отвечают за установку плагинов CNI на каждый узел кластера. Их местонахождение также настраивается; директория по умолчанию — /opt/cni/bin.
При использовании containerd пути для конфига и бинарников плагина можно задать в разделе [plugins.«io.containerd.grpc.v1.cri».cni] в
You must be registered for see links
.Поскольку мы используем Flannel в качестве сетевого провайдера, давайте немного поговорим о его настройке:
- Flanneld (демон Flannel'а) обычно устанавливается в кластер как DaemonSet с install-cni в качестве
You must be registered for see links.
- Install-cni создает
You must be registered for see links(/etc/cni/net.d/10-flannel.conflist) на каждом узле.
- Flanneld создает устройство vxlan, извлекает сетевые метаданные с API-сервера и следит за обновлениями pod'ов. По мере их создания он распространяет маршруты для всех pod'ов по всему кластеру.
- Эти маршруты и позволяют pod'ам связываться друг с другом по IP-адресам.
Для получения более подробной информации о работе Flannel рекомендую воспользоваться ссылками в конце статьи.
Вот схема взаимодействия между плагином Containerd CRI и плагинами CNI:
Как видно выше, kubelet вызывает плагин Containerd CRI, чтобы создать pod, а тот уже вызывает плагин CNI для настройки сети pod'а. При этом CNI-плагин сетевого провайдера вызывает другие базовые плагины CNI для настройки различных аспектов сети.
Взаимодействие между CNI-плагинами
Существуют различные плагины CNI, задача которых — помочь настроить сетевое взаимодействие между контейнерами на хосте. В этой статье речь пойдет о трех из них.
CNI-плагин Flannel
При использовании Flannel в качестве сетевого провайдера компонент Containerd CRI вызывает
You must be registered for see links
, используя конфигурационный файл 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-мост в сети хоста.
You must be registered for see links
подключает все контейнеры хоста к Linux-мосту в сети хоста.Закончив с настройкой пары veth, плагин Bridge вызывает локальный для хоста (host-local) CNI-плагин IPAM. Тип IPAM-плагина можно настроить в конфиге CNI, который плагин CRI использует для вызова CNI-плагина Flannel.
Локальные для хоста IPAM-плагины CNI
Bridge CNI вызывает
You must be registered for see links
со следующей конфигурацией:{
"name": "cni0",
"ipam": {
"type": "host-local",
"subnet": "10.244.0.0/24",
"dataDir": "/var/lib/cni/networks"
}
}
Host-local IPAM-плагин (IP Address Management — управление IP-адресами) возвращает IP-адрес для контейнера из подсети и сохраняет выделенный IP на хосте в директории, указанной в разделе dataDir — /var/lib/cni/networks//. В этом файле содержится 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. Если я в чем-то ошибаюсь, пожалуйста, свяжитесь со мной в
You must be registered for see links
или по адресу [email protected]. Не стесняйтесь обращаться, если захотите обсудить аспекты этой статьи или что-нибудь другое. Я с удовольствием пообщаюсь с вами!Ссылки
Контейнеры и сеть
-
You must be registered for see links
-
You must be registered for see links
Как работает Flannel
-
You must be registered for see links
-
You must be registered for see links
CRI и CNI
-
You must be registered for see links
-
You must be registered for see links
-
You must be registered for see links
P.S. от переводчика
Читайте также в нашем блоге:
- «
You must be registered for see links»;
- «Иллюстрированное руководство по устройству сети в Kubernetes»:
You must be registered for see links,You must be registered for see links;
- «
You must be registered for see links».