Привет, Хабр! Сегодня у нас на повестке дня тема кастомизации сетевого стека в Kubernetes с Cilium.
Cilium — это сетевое решение, которое работает прямо в ядре Linux и построено на основе eBPF. Его главная задача — обеспечить эффективное, а главное, безопасное взаимодействие между подами в кластере Kubernetes. И это не просто замена стандартному kube-proxy. Это полноценный инструмент для построения сетевых политик, мониторинга и кастомизации сетевого стека.
Основные фичи:
Гибкие сетевые политики: можно задать фильтры трафика на уровнях L3 (IP), L4 (TCP/UDP) и L7 (HTTP, gRPC).
Интеграция с Envoy: вместо того, чтобы ограничиваться стандартными функциями, вы можете подключить Envoy для управления сетевыми запросами или даже написать собственные программы на eBPF для уникальных задач.
Устранение узких мест: Cilium устраняет проблемы масштабирования iptables, переходя к использованию eBPF, который выполняет фильтрацию и маршрутизацию пакетов непосредственно в ядре Linux. Вместо линейного перебора правил, как в iptables, eBPF использует хэш-таблицы и карты, которые дают мгновенный доступ к нужным данным. Так трафик обратывается быстрее, с меньшей нагрузкой на процессор и без создания узких мест.
Установим
Перед тем как начать, убедитесь, что у вас есть:
Kubernetes-кластер.
Доступ к CLI kubectl.
Рабочий helm.
Установим Cilium CLI:
curl -L --remote-name https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64
chmod +x cilium-linux-amd64
sudo mv cilium-linux-amd64 /usr/local/bin/cilium
После устанавливаем Cilium с помощью Helm:
helm repo add cilium https://helm.cilium.io/
helm repo update
helm install cilium cilium/cilium \
--namespace kube-system \
--set kubeProxyReplacement=strict \
--set k8sServiceHost= \
--set k8sServicePort=
Проверяем статус:
kubectl -n kube-system get pods -l k8s-app=cilium
Если все поды в состоянии Running
, можно двигаться дальше.
Кастомизация сетевых политик
Cilium позволяет создавать сетевые политики, которые гораздо мощнее стандартных NetworkPolicy в Kubernetes. Рассмотрим пару примеров.
Ограничение доступа по L7
Допустим, есть два пода: frontend
и backend
. Задача — разрешить доступ от frontend к backend только для HTTP GET-запросов.
Создаем CiliumNetworkPolicy:
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-http-get
namespace: default
spec:
endpointSelector:
matchLabels:
app: backend
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "80"
protocol: TCP
rules:
http:
- method: "GET"
path: "/.*"
Применяем политику:
kubectl apply -f allow-http-get.yaml
Теперь фронтенд может обращаться к бэкенду только через GET-запросы. Попробуйте отправить POST-запрос — и он будет заблокирован.
Ограничение исходящего трафика
Допустим, нужно ограничить доступ из frontend
ко всем внешним ресурсам, кроме одного сервиса.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: restrict-egress
namespace: default
spec:
endpointSelector:
matchLabels:
app: frontend
egress:
- toEntities:
- world
toEndpoints:
- matchLabels:
app: trusted-service
toPorts:
- ports:
- port: "443"
protocol: TCP
Применяем эту политику:
kubectl apply -f restrict-egress.yaml
Теперь трафик из frontend
будет ограничен только к определённым ресурсам.
Разрешение доступа только к определенному домену
Теперь разрешим поду доступ только к домену example.com
через HTTPS.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-specific-domain
namespace: default
spec:
endpointSelector:
matchLabels:
app: frontend
egress:
- toFQDNs:
- matchNames:
- "example.com"
toPorts:
- ports:
- port: "443"
protocol: TCP
Применяем:
kubectl apply -f allow-specific-domain.yaml
Теперь трафик из frontend
будет разрешён только к example.com
.
Ограничение доступа между namespace
Допустим, есть два namespace: dev
и prod
. Нужно запретить всем подам из dev
доступ к подам в prod
, кроме одного сервиса.
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: restrict-dev-to-prod
namespace: prod
spec:
endpointSelector:
matchLabels:
app: prod-service
ingress:
- fromEndpoints:
- matchLabels:
namespace: dev
app: allowed-dev-app
Применяем политику:
kubectl apply -f restrict-dev-to-prod.yaml
Теперь только под allowed-dev-app
из dev
может обращаться к prod-service
в prod
.
Мониторинг трафика с Hubble
Hubble — это встроенный инструмент для мониторинга трафика в Cilium. Его установка занимает пару минут:
cilium hubble enable
cilium hubble ui
Открываем веб-интерфейс Hubble и наблюдаем за всем, что происходит в сети кластера. Можно будет увидеть:
Какие поды взаимодействуют друг с другом.
Какие запросы блокируются политиками.
Статистику по каждому сервису.
Кастомные eBPF-программы
Если очень хочется пойти дальше, Cilium позволяет загружать свои eBPF-программы для реализации специфичных задач. Например, можно написать фильтр, который будет логировать только трафик, идущий через определенный порт.
Простой пример фильтра на eBPF, который логирует HTTP-трафик:
#include
#include
#include
int log_http(struct __sk_buff *skb) {
char msg[] = "HTTP request detected\n";
bpf_trace_printk(msg, sizeof(msg));
return 0;
}
Компилируем и загружаем:
ebpf-loader -o http_filter.o -s log_http.c
Загружаем программу через Cilium:
cilium bpf install http_filter.o
Теперь каждый HTTP-запрос будет логироваться на уровне ядра.
Фильтрация по IP
Добавим фильтр, который блокирует трафик с определённого IP-адреса:
#include
#include
#include
int block_ip(struct __sk_buff *skb) {
struct iphdr *ip = bpf_hdr_pointer(skb);
if (ip->saddr == htonl(0xC0A80001)) { // 192.168.0.1
return TC_ACT_SHOT; // Drop packet
}
return TC_ACT_OK;
}
Загружаем этот фильтр аналогично:
ebpf-loader -o block_ip.o -s block_ip.c
cilium bpf install block_ip.o
Теперь пакеты с заданного IP-адреса будут блокироваться.
Подробнее с Cilium можно ознакомиться здесь.
Больше об актуальных подходах и инструментах ИТ-инфраструктуры вы можете узнать в рамках онлайн-курсов от практикующих экспертов отрасли. Подробности в каталоге.
А 24 декабря пройдет открытый урок «Технология контейнеризации, введение в Docker» — записаться можно на странице курса «DevOps практики и инструменты».