Cilium ingress с выделенным балансировщиком нагрузки: внешний доступ

Вопрос или проблема

Проблема:

Я хотел бы получить доступ к приложению, размещенному за Cilium ingress в моем кластере на физическом оборудовании. Однако я могу получить к нему доступ только с узла, а не с внешней системы. Я не уверен, правильно ли все настроено и какую комбинацию IP:PORT я должен использовать.

Настройка:

У меня есть кластер Kubernetes с двумя узлами, настроенный с использованием Multipass (две машины с Ubuntu 24.04). Я объединил сеть, чтобы обе виртуальные машины находились в том же адресном пространстве, что и хост виртуальной машины. Я изменил порядок шлюзов по умолчанию с помощью netplan перед настройкой кластера, чтобы Kubernetes использовал адресное пространство моей домашней сети.

Я использовал Cilium в качестве CNI, заменяющего kube proxy и провайдера ingress. Я использовал L2 объявления для внешних и IP-адресов балансировщика нагрузки со следующими значениями для Helm chart:

# values.yaml для Helm chart
ipam:
  operator:
    clusterPoolIPv4MaskSize: 24
    clusterPoolIPv4PodCIDRList:
    - 10.42.0.0/16
k8s:
  requireIPv4PodCIDR: true
ingressController:
  enabled: true
  default: true
  service:
    externalTrafficPolicy: Cluster
    type: LoadBalancer
  loadbalancerMode: dedicated
kubeProxyReplacement: true
l2announcements:
  enabled: true
externalIPs:
  enabled: true
loadBalancerIPs:
  enabled: true

CIDR для сети подов также был передан kubeadm init как --pod-network-cidr=10.42.0.0/16.

После настройки всего я создал пул IP-адресов балансировщика нагрузки Cilium, чтобы мои новые балансировщики ingress получали внешние IP-адреса:

apiVersion: "cilium.io/v2alpha1"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "default-pool"
spec:
  blocks:
  - cidr: "10.31.0.0/24"

Затем я создал тестовый Под с использованием изображения nginx и открыл его на порту 80, используя сервис ClusterIP:

NAME             READY   STATUS    RESTARTS   AGE   IP            NODE         NOMINATED NODE   READINESS GATES
pod/test-nginx   1/1     Running   0          18h   10.42.1.108   k8s-worker   <none>           <none>

NAME       TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE   SELECTOR
test-svc   ClusterIP   10.100.113.198   <none>        80/TCP    18h   run=test-nginx

Затем я создал соответствующий объект ingress:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: test-ingress
  annotations:
    ingress.cilium.io/loadbalancer-class: io.cilium/l2-announcer
spec:
  ingressClassName: cilium
  rules:
  - host: test-site.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: test-svc
            port:
              number: 80

Он получил внешний IP из пула:

NAME           CLASS    HOSTS           ADDRESS     PORTS   AGE
test-ingress   cilium   test-site.com   10.31.0.0   80      45m

Базовый балансировщик нагрузки в пространстве kube-system и выделенный балансировщик нагрузки также запущены:

NAME             TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
cilium-ingress   LoadBalancer   10.109.159.64   10.31.0.1     80:31577/TCP,443:31560/TCP   18h

NAME                          TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                      AGE
cilium-ingress-test-ingress   LoadBalancer   10.99.218.182   10.31.0.0     80:30262/TCP,443:30638/TCP   47m

Наконец, я записал 10.31.0.0 test-site.com в /etc/hosts на управляющем узле и выполнил curl http://test-site.com:80 против него. Это дало ожидаемый вывод:

root@k8s-master:~# curl http://test-site.com:80/

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Затем я попробовал то же самое на хост-машине (которая находится в том же адресном пространстве, что и управляющий узел ВМ), и это не сработало.

$: curl -v http://test-site.com:80/ --resolve "test-site.com:80:10.31.0.0"
* Added test-site.com:80:10.31.0.0 в DNS кэш
* Hostname test-site.com был найден в DNS кэш
*   Trying 10.31.0.0:80...

Я пробовал разные IP и порты.

Нужно ли мне создать еще одно виртуальное соединение с адресным пространством 10.31.0.0/24 с моей хост-машины?

Ответ или решение

Понимание работы с Cilium и управлением трафиком в Kubernetes-кластере на основе предоставленного описания — ключ к успешной реализации подключения внешних пользователей к вашему внутреннему приложению через Ingress. Рассмотрим, как обеспечить внешнюю доступность приложения, находящегося за Cilium Ingress, с выделенным балансировщиком нагрузки в контексте изученного вопроса.

Теория

Прежде чем приступить к детальному разбору, важно понять теоретические концепции, связанные с работой сети Kubernetes и Cilium как сетевого решения. Kubernetes использует различные механизмы маршрутизации и балансировки нагрузки для предоставления доступа к контейнеризированным приложениям. В этом контексте Cilium действует как контейнерная сеть (CNI), заменитель kube-proxy и провайдер Ingress.

Cilium, как CNI и Ingress

  1. Cilium как CNI: Cilium предоставляет расширенные возможности сетевой политики, что позволяет программно контролировать трафик между контейнерами. Оно использует eBPF (Extended Berkeley Packet Filter) для высокопроизводительного доступа к данным сети и управления ими.

  2. Ingress и балансировщик нагрузки: Ingress в Kubernetes позволяет определить правила маршрутизации внешнего доступа к сервисам в кластере. Cilium Ingress с поддержкой L2 Anouncements позволяет рекламу IP-адресов на канальном уровне и настройку статических IP-адресов для балансировщиков нагрузки.

Пример

Уже указанная вами конфигурация Helm для Cilium предусматривает использование L2 Announcements и выделение статического IP для балансировщика нагрузки:

ingressController:
  enabled: true
  default: true
  service:
    externalTrafficPolicy: Cluster
    type: LoadBalancer
  loadbalancerMode: dedicated

Это необходимое условие для обеспечения работы с IP-пулами и маршрутизации внешнего трафика посредством балансировщика нагрузки.

Создание IP Pool для LoadBalancer также является важным шагом:

apiVersion: "cilium.io/v2alpha1"
kind: CiliumLoadBalancerIPPool
metadata:
  name: "default-pool"
spec:
  blocks:
  - cidr: "10.31.0.0/24"

Ваша конфигурация позволяет ingress получить внешний IP-адрес из указанного пула, что видно в разделе:

test-ingress   cilium   test-site.com   10.31.0.0   80      45m

Применение

Теперь, когда вы разобрались с теорией и примерами конфигурации, важно сфокусироваться на применении этой настройки для решения проблемы с недоступностью извне.

Диагностика проблемы

  1. Сетевая связанность и адресное пространство: Убедитесь, что ваше внешнее устройство (например, хост-машина) имеет доступ к сети, в которой находится пул выделенных IP-адресов, будучи в том же адресном пространстве. Если это не так, возможно, потребуется настроить маршрут в вашей сети так, чтобы запросы могли достигать этого диапазона IP-адресов.

  2. Проверка IP-адреса и порта: Посмотрите активность трафика на уровне узлов вашего Kubernetes-кластера. Возможно, пакеты не доходят до конечного узла. Используйте утилиты наподобие tcpdump для отслеживания сетевых потоков или iptables для проверки правил маршрутизации и NAT.

  3. Конфигурация L2 Announcements: Убедитесь, что L2 Announcements правильно настроены и работают. Может оказаться полезным заглянуть в журналы Cilium, чтобы проверить, как обрабатываются арпы и другие сетевые запросы.

  4. Преобразование сетевого трафика: Подтвердите, что балансировщик нагрузки правильно маршрутизирует трафик между внешним миром и вашим приложением. Для этого может потребоваться настройка IPtable правил или проверка сетевых маршрутов для вашего Kubernetes-кластера.

  5. DNS и /etc/hosts: Хотя вы успешно добавили 10.31.0.0 test-site.com в файл /etc/hosts на управляющем узле, необходимо проверить, как устройство, отправляющее запросы, разрешает это имя.

Возможные решения

  1. Настройка маршрутов: Если ваше внешнее устройство физически не может достичь IP 10.31.0.0, настройте маршрутизацию на уровне вашей домашней сети или создайте туннель между сетями.

  2. Проверка правил firewall: Убедитесь, что на ваших маршрутизаторах и узлах Kubernetes нет правил firewall, блокирующих внешний доступ.

  3. Корректировка сетевых интерфейсов: Проверьте, правильно ли конфигурированы сетевые интерфейсы на ваших узлах. Иногда сетевые карты виртуальных машин нуждаются в дополнительной настройке для общения с другими устройствами на вашем хосте.

Таким образом, уделив внимание этим аспектам, вы сможете обеспечить внешний доступ к приложению, находящемуся за Cilium Ingress в вашем Kubernetes-кластере. Внимательное изучение сетевой конфигурации и корректная настройка инфраструктуры — ключ к решению описанных проблем.

Оцените материал
Добавить комментарий

Капча загружается...