Вопрос или проблема
Проблема:
Я хотел бы получить доступ к приложению, размещенному за 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
-
Cilium как CNI: Cilium предоставляет расширенные возможности сетевой политики, что позволяет программно контролировать трафик между контейнерами. Оно использует eBPF (Extended Berkeley Packet Filter) для высокопроизводительного доступа к данным сети и управления ими.
-
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
Применение
Теперь, когда вы разобрались с теорией и примерами конфигурации, важно сфокусироваться на применении этой настройки для решения проблемы с недоступностью извне.
Диагностика проблемы
-
Сетевая связанность и адресное пространство: Убедитесь, что ваше внешнее устройство (например, хост-машина) имеет доступ к сети, в которой находится пул выделенных IP-адресов, будучи в том же адресном пространстве. Если это не так, возможно, потребуется настроить маршрут в вашей сети так, чтобы запросы могли достигать этого диапазона IP-адресов.
-
Проверка IP-адреса и порта: Посмотрите активность трафика на уровне узлов вашего Kubernetes-кластера. Возможно, пакеты не доходят до конечного узла. Используйте утилиты наподобие
tcpdump
для отслеживания сетевых потоков илиiptables
для проверки правил маршрутизации и NAT. -
Конфигурация L2 Announcements: Убедитесь, что L2 Announcements правильно настроены и работают. Может оказаться полезным заглянуть в журналы Cilium, чтобы проверить, как обрабатываются арпы и другие сетевые запросы.
-
Преобразование сетевого трафика: Подтвердите, что балансировщик нагрузки правильно маршрутизирует трафик между внешним миром и вашим приложением. Для этого может потребоваться настройка IPtable правил или проверка сетевых маршрутов для вашего Kubernetes-кластера.
-
DNS и /etc/hosts: Хотя вы успешно добавили
10.31.0.0 test-site.com
в файл/etc/hosts
на управляющем узле, необходимо проверить, как устройство, отправляющее запросы, разрешает это имя.
Возможные решения
-
Настройка маршрутов: Если ваше внешнее устройство физически не может достичь IP 10.31.0.0, настройте маршрутизацию на уровне вашей домашней сети или создайте туннель между сетями.
-
Проверка правил firewall: Убедитесь, что на ваших маршрутизаторах и узлах Kubernetes нет правил firewall, блокирующих внешний доступ.
-
Корректировка сетевых интерфейсов: Проверьте, правильно ли конфигурированы сетевые интерфейсы на ваших узлах. Иногда сетевые карты виртуальных машин нуждаются в дополнительной настройке для общения с другими устройствами на вашем хосте.
Таким образом, уделив внимание этим аспектам, вы сможете обеспечить внешний доступ к приложению, находящемуся за Cilium Ingress в вашем Kubernetes-кластере. Внимательное изучение сетевой конфигурации и корректная настройка инфраструктуры — ключ к решению описанных проблем.