Calico

Режимы работы

Calico поддерживает три режима:

  • Direct — когда поды могут обращаться к другим подам кластера через обычные сетевые соединения без использовани различных видов тунелей (инкапсуляций пакетов).
  • IP-in-IP — используется возможность Linux: IP in IP tunneling
  • VXLAN — инкапсуляция L2 в UDP пакеты. Virtual eXtensible Local Area Networking documentation

Если машины кластера находятся в одной сети, лучшим выбором будет отсутствие любых overlay.

Установка драйвера сети

Если вы используете NetworkManager, его необходимо настроить перед использованием Calico.

Создадим конфигурационный файл /etc/NetworkManager/conf.d/calico.conf, что бы запретить NetworkManager работать с интерфейсами, управляемыми calico:

[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico

Скачаем необходимые для установки файлы.

curl -s https://docs.projectcalico.org/manifests/calico.yaml -O

В файле заменим

- name: CALICO_IPV4POOL_IPIP
  value: "Always"
# - name: CALICO_IPV4POOL_CIDR
#   value: "192.168.0.0/16"

на

- name: CALICO_IPV4POOL_IPIP
  value: "Never"
- name: CALICO_IPV4POOL_CIDR
  value: "192.168.180.0/24"

Переменная определяет режим работы сети. Отключив оба режима оверлея, мы включаем Direct режим сети.

Можно заменить размер блока (маска подсети), выделяемого на ноду (Значение по умолчанию — 26):

- name: CALICO_IPV4POOL_BLOCK_SIZE
  value: 25

Подробное описание параметров, используемых при конфигурации calico/node, можно посмотреть в документации.

Установим calico.

kubectl apply -f calico.yaml

Смотрим, вникаем

Сначал посмотрим какие IP адреса получили поды в namespace kube-system

watch kubectl -n kube-system get pods -o wide

Смотрим таблицы маршрутизации на всех нодах кластера

route -n

Обращаем внимание на интерфейсы типа cali*.

Запускаем nginx на 3-ей ноде кластера.

kubectl run --image=nginx:latest nginx \
    --overrides='{"apiVersion": "v1", "spec": {"nodeSelector": { "kubernetes.io/hostname": "ip-174-163.kryukov.local" }}}'

Смотрим, какой ip адрес был выдан поду

kubectl get pods -o wide 

Попытаемся подключиться к ngix в этом поде.

Почему у нас ничего не получается?

Установка утилиты calicoctl

calicoctl позволяет управлять параметрами сети.

Утилиту можно поставить непосредственно в кластер kubernetes в виде отдельного пода. Или как бинарный файл непосредственно в Linux.

curl -s https://raw.githubusercontent.com/BigKAA/youtube/master/net/02-calico/01-install-calicoctl.sh | bash

Создаем конфигурационный файл программы.

curl -s https://raw.githubusercontent.com/BigKAA/youtube/master/net/02-calico/02-calicoctl.cfg -o /etc/calico/calicoctl.cfg 

Проверяем работу программы

calicoctl get nodes
calicoctl node status

Замена механизма оверлея

calicoctl get ippool default-ipv4-ippool -o yaml > pool.yaml
vim pool.yaml
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  creationTimestamp: "2020-11-08T17:41:07Z"
  name: default-ipv4-ippool
  resourceVersion: "2278"
  uid: 3da935c0-63ba-4c24-b63d-9f49b7549855
spec:
  blockSize: 26
  cidr: 192.168.180.0/24
  ipipMode: Never
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never

В файле заменим параметры

ipipMode: Never -> Always

Применим полученную конфигурацию.

calicoctl apply -f pool.yaml

Смотрим на всех нодах кластера таблицу маршрутизации.

route -n

Пытаемся подключиться к nginx.

Снова открываем на редактирование pool.yaml изаменяем

ipipMode: Always -> CrossSubnet

Удаляем строки:

creationTimestamp:
resourceVersion:
uid: 

Применим полученную конфигурацию.

calicoctl apply -f pool.yaml

Смотрим на всех нодах кластера таблицу маршрутизации. Делаем выводы.

Calico IPAM

Kubernetes использует плагины IPAM (IP Adress Management) для выделения IP адресов подам. Проект calico предоставляет модуль: calico-ipam.

Модуль calico-ipam использует Calico IP pool для определения каким образом выделять IP адреса для подов в кластере.

calicoctl get ippool

По умолчанию используется один IP pool для всего кластера. Но его можно разделить на несколько пулов. В дальнейшем эти пулы можно назначать на под используя различные условия выбора:

  • node selectos,
  • аннотаций к namespaces,
  • аннотаций к подам.

Calico разделяет пулы на меньшие по размеру блоки, которые прикрепляются к node. Мы уже видели эти блоки, когда смотрели таблицу маршрутизации ноды. К каждой ноде кластера может быть подключен один или несколько таких блоков. Calico будет самостоятельно добавлять и удалять их.

По умолчанию размер блока соответствует подсети /26 (64 адреса). Это параметр можно изменить как в процессе установки calico, так и во время обычной работы кластера.

calicoctl get ippool default-ipv4-ippool -o yaml
calicoctl ipam show

Назначение пула IP адресов

Существует несколько вариантов назначения пула IP адресов. Мы посмотрим наиболее часто используемый при создании территориально распределенных кластеров.

Предположим, что первые две ноды нашего кластера расположены в одном датацентре, а третья в другом. Сеть подов кластера: 192.168.180.0/24

Необходимо, что бы первые две ноды были в подсети 192.168.200.0/24, а третья в 192.168.201.0/24

Нам потребуется выполнить следующие действия:

  • Поставить метки на ноды кластера.
  • Создать два IP пула, с определением нод кластера, на какие они будут применяться.
  • Перевод пула default-ipv4-ippool в состяние disabled.
  • Удалить (перезапустить) поды, что бы они при создании получили IP адреса из новых пулов.
  • Удалить пул default-ipv4-ippool.

Ставим метки на ноды кластера:

kubectl label nodes ip-218-161 location=datacenter1
kubectl label nodes ip-218-162 location=datacenter1
kubectl label nodes ip-174-163.kryukov.local location=datacenter2
kubectl get nodes --show-labels

Создаём два пула:

---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
   name: datacenter1
spec:
   cidr: 192.168.200.0/24
   ipipMode: CrossSubnet
   natOutgoing: true
   nodeSelector: location == "datacenter1"
---
apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
   name: datacenter2
spec:
   cidr: 192.168.201.0/24
   ipipMode: CrossSubnet
   natOutgoing: true
   nodeSelector: location == "datacenter2"
calicoctl apply -f pool-locations.yaml
calicoctl get ippool

Переводим пул default-ipv4-ippool в состяние disabled.

calicoctl get ippool default-ipv4-ippool -o yaml > pool.yaml
vim pool.yaml

Удаляем строки:

creationTimestamp:
resourceVersion:
uid: 

Добавляем:

disabled: true

Получается файл следующего содержимого:

apiVersion: projectcalico.org/v3
kind: IPPool
metadata:
  name: default-ipv4-ippool
spec:
  blockSize: 26
  cidr: 192.168.180.0/24
  ipipMode: CrossSubnet
  natOutgoing: true
  nodeSelector: all()
  vxlanMode: Never
  disabled: true

Применяем конфиг.

calicoctl apply -f pool.yaml
calicoctl get ippool -o wide

Смотрим какие поды работают на старых ip в сети:

kubectl get pods --all-namespaces -o wide | grep 192.168.180

Удаляем их.

kubectl -n kube-system rollout restart deployment/calico-kube-controllers
kubectl -n kube-system rollout restart deployment.apps/coredns
kubectl delete pod/nginx

Запускаем nginx на третей ноде:

kubectl run --image=nginx:latest nginx \
    --overrides='{"apiVersion": "v1", "spec": {"nodeSelector": { "kubernetes.io/hostname": "ip-174-163.kryukov.local" }}}'

Смотрим что получилось.

kubectl get pods -o wide --all-namespaces | grep -E '192.168.200|192.168.201'
route -n

Удаляем пул.

calicoctl delete pool default-ipv4-ippool
calicoctl get ippool
route -n

Заключение

Мы рассмотрели пример установки calico для кластера до 50-ти нод. Поэтому я упустил вопросы связанные с настройкой BGP. Но радует то, что на сайте у calico превосходно написанная документация и эти вопросы можно найти там.