- Вопрос или проблема
- Ответ или решение
- Подключение клиента OpenVPN к подам Kubernetes: Решение проблем с маршрутизацией
- Введение
- Текущая ситуация
- Искусственная изоляция и проблема маршрутизации
- Решение проблем
- 1. Настройки маршрутизации
- 2. Применение Kubernetes NetworkPolicy
- 3. Использование iptables
- 4. Поддержка маршрутизации
- 5. Тестирование
- Заключение
Вопрос или проблема
Я относительно нов в сетях и Kubernetes, но мне нужно провести нагрузочное тестирование сервера OpenVPN.
Вот что я сделал до сих пор:
Я создал образ Docker, который включает клиент OpenVPN.
Я настроил кластер Kubernetes с помощью Minikube, чтобы запустить Job, который выполняет Pods, содержащие мой образ Docker с OpenVPN.
Я использую Calico в режиме IPinIP.
Я настроил Service с NodePort.
Когда я запускаю свои Pods, я успешно устанавливаю VPN туннель. Я могу это подтвердить, потому что:
Интерфейс tun смонтирован в каждом из моих Pods.
Логи сервера и статусный файл показывают, что туннели открыты.
Однако я сталкиваюсь с проблемой: интерфейс tun0 в моих Pods фактически бесполезен. Насколько я понимаю, он неправильно маршрутизируется за пределами моего узла. Я в тупике и не могу понять, как заставить интерфейс tun0 в моих Pods подключаться внешне через Calico.
Ниже представлены некоторые команды, которые я использовал, чтобы понять свою проблему в моем поде.
Ping с использованием интерфейса tun0
module-update-job-0:/home/root# ping 8.8.8.8 -I tun0
PING 8.8.8.8 (8.8.8.8): 56 data bytes
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 0 packets received, 100% packet loss
Ping с использованием интерфейса eth0
module-update-job-0:/home/root# ping 8.8.8.8 -I eth0
PING 8.8.8.8 (8.8.8.8): 56 data bytes
64 bytes from 8.8.8.8: seq=0 ttl=113 time=10.461 ms
64 bytes from 8.8.8.8: seq=1 ttl=113 time=10.380 ms
64 bytes from 8.8.8.8: seq=2 ttl=113 time=13.003 ms
^C
--- 8.8.8.8 ping statistics ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 10.380/11.281/13.003 ms
Интерфейсы, смонтированные в моем поде
module-update-job-0:/home/root# ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo valid_lft forever preferred_lft forever inet6 ::1/128 scope host proto kernel_lo valid_lft forever preferred_lft forever
2: tunl0@NONE: <NOARP> mtu 1480 qdisc tbf state DOWN group default qlen 1000 link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if42: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc tbf state UP group default qlen 1000
link/ether 9e:39:6c:ed:65:38 brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 192.168.100.81/32 scope global eth0 valid_lft forever preferred_lft forever
inet6 fe80::9c39:6cff:feed:6538/64 scope link proto kernel_ll
valid_lft forever preferred_lft forever
5: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1380 qdisc tbf state UNKNOWN group default qlen 500
link/none
inet 192.168.X.X peer 192.168.X.X/32 scope global tun0
valid_lft forever preferred_lft forever
inet6 fe80::bcc5:57a:f07e:b61a/64 scope link stable-privacy proto kernel_ll
valid_lft forever preferred_lft forever
Маршруты в моих подах после выполнения VPN клиента
module-update-job-0:/home/root# routes
bash: routes: command not found
module-update-job-0:/home/root# route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
default 192.168.16.5 128.0.0.0 UG 0 0 0 tun0
default 169.254.1.1 0.0.0.0 UG 0 0 0 eth0
128.0.0.0 192.168.16.5 128.0.0.0 UG 0 0 0 tun0
169.254.1.1 * 255.255.255.255 UH 0 0 0 eth0
172.17.16.79 169.254.1.1 255.255.255.255 UGH 0 0 0 eth0
192.168.16.0 192.168.16.5 255.255.240.0 UG 0 0 0 tun0
192.168.16.5 * 255.255.255.255 UH 0 0 0 tun0
Traceroute через eth0
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 46 byte packets
1 192.168.49.2 (192.168.49.2) 0.006 ms 0.040 ms 0.034 ms
2 192.168.49.1 (192.168.49.1) 0.008 ms 0.010 ms 0.007 ms
3 192.168.200.254 (192.168.200.254) 0.528 ms 0.571 ms 0.436 ms
4 X.X.X.X (X.X.X.X) 1.083 ms 1.115 ms 1.052 ms
5 X.X.X.X (X.X.X.X) 2.156 ms 2.117 ms 2.109 ms
6 X.X.X.X (X.X.X.X) 12.101 ms 11.581 ms 13.382 ms
7 X.X.X.X (X.X.X.X) 10.640 ms 12.218 ms 12.060 ms
8 X.X.X.X (X.X.X.X) 11.569 ms 14.146 ms 12.000 ms
9 X.X.X.X (X.X.X.X) 10.433 ms 10.512 ms 10.330 ms
10 X.X.X.X (X.X.X.X) 10.355 ms 94.228.177.30 (94.228.177.30) 10.937 ms 11.495 ms
11 * * *
12 8.8.8.8 (8.8.8.8) 10.430 ms 10.304 ms 142.250.234.41 (142.250.234.41) 10.975 ms
Traceroute через tun0
module-update-job-0:/home/root# traceroute 8.8.8.8 -i tun0
traceroute to 8.8.8.8 (8.8.8.8), 30 hops max, 46 byte packets
1 192.168.16.1 (192.168.16.1) 11.639 ms 11.637 ms 11.398 ms
2 * * *
3 * * *
Ниже приведено определение моей задачи Kubernetes,
Конфигурация Job
Символы ‘%’ заполняются с помощью sed в Bash-скрипте.
apiVersion: batch/v1
kind: Job
metadata:
name: module-update-job
spec:
completions: %COMPLETION%
parallelism: %PARALLELISM%
completionMode: Indexed
template:
metadata:
labels:
app: module-update-pod
annotations:
#k8s.v1.cni.cncf.io/networks: "direct-host-network"
#cni.projectcalico.org/ipv4pools: "[\"192.168.100.0/24\"]"
spec:
containers:
- name: module-update-conn
image: module-update:latest
imagePullPolicy: Never
securityContext:
privileged: true
capabilities:
add:
- NET_ADMIN
- NET_RAW
tty: dev
stdin: true
env:
- name: POD_ID
valueFrom:
fieldRef:
fieldPath: metadata.name # Уникальное имя пода как BOARD_ID
- name: JOB_COMPLETION_INDEX
valueFrom:
fieldRef:
fieldPath: metadata.annotations['batch.kubernetes.io/job-completion-index']
- name: GATEWAY_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
ports:
- containerPort: 5686
protocol: UDP
- containerPort: 21
protocol: TCP # FTP контрольный канал
volumeMounts:
# Индивидуальные сопоставления файлов
- name: client-crt
mountPath: /media/edenv/openvpn/client.crt
- name: client-key
mountPath: /media/edenv/openvpn/client.key
- name: ca-crt
mountPath: /media/edenv/openvpn/ca.crt
- name: conf
mountPath: /etc/openvpn/client.conf
- name: script-down
mountPath: /etc/openvpn/script_down.sh
- name: scripts
mountPath: /home/root/.
- name: tun-device
mountPath: /dev/net/tun
command: [./integration_test.sh, "k8s", "%VPN_IP%", "%VPN_PORT%"]
restartPolicy: Never
volumes:
# Определите пути хоста
- name: client-crt
hostPath:
path: %HOME%/ed-load-testing-tools/k8s-integration-test/secret/client.crt
type: File
- name: client-key
hostPath:
path: %HOME%/ed-load-testing-tools/k8s-integration-test/secret/client.key
type: File
- name: ca-crt
hostPath:
path: %HOME%/ed-load-testing-tools/k8s-integration-test/secret/ca.crt
type: File
- name: conf
hostPath:
path: %HOME%/ed-load-testing-tools/k8s-integration-test/openvpn/client.conf
type: File
- name: script-down
hostPath:
path: %HOME%/ed-load-testing-tools/k8s-integration-test/openvpn/script_down.sh
type: File
- name: scripts
hostPath:
path: %HOME%/ed-load-testing-tools/k8s-integration-test/scripts
type: Directory
- name: tun-device
hostPath:
path: /dev/net/tun
type: CharDevice
---
apiVersion: v1
kind: Service
metadata:
name: module-update-service
namespace: default
spec:
selector:
app: module-update-pod
ports:
- protocol: UDP
name: udp
port: 5686 # Открытый порт сервиса
targetPort: 5686 # Порт контейнера, сопоставленный
- protocol: TCP
name: ftp-crtl
port: 21 # FTP контрольный канал
targetPort: 21
- protocol: TCP
name: ftp-data
port: 5000 # Порты данных FTP в пассивном режиме
targetPort: 5000
type: NodePort
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress-egress
namespace: default
spec:
podSelector: {}
policyTypes:
- Ingress
- Egress
ingress:
- {}
egress:
- {}
Ответ или решение
Подключение клиента OpenVPN к подам Kubernetes: Решение проблем с маршрутизацией
Введение
Вам необходимо выполнить нагрузочное тестирование сервера OpenVPN, используя кластеры Kubernetes, созданные с Minikube. На данный момент вы успешно настроили клиент OpenVPN внутри контейнеров, однако столкнулись с проблемой маршрутизации трафика через интерфейс tun0
. Давайте подробно разберем, как правильно установить маршрутизацию для вашего клиента OpenVPN, чтобы обеспечить корректное подключение из подов Kubernetes.
Текущая ситуация
-
Создание образа Docker: Вы успешно создали образ, содержащий клиента OpenVPN, и настроили рабочее окружение в Kubernetes.
-
Подключение к OpenVPN: Вы смогли установить VPN-туннель, что подтверждается состоянием интерфейса
tun0
и записями в логах сервера. Однако, несмотря на успешное соединение, пакеты не проходят черезtun0
. -
Различия в маршрутизации: При пинге на внешний IP-адрес (например, 8.8.8.8) через интерфейс
tun0
пакеты не доходят, в отличие отeth0
, где вы видите успешные ответы.
Искусственная изоляция и проблема маршрутизации
При использовании CNI Calico в режиме IP-in-IP, трафик, идущий на интерфейс tun0
, может не маршрутизироваться должным образом. Поскольку tun0
– это виртуальный интерфейс, его маршрутизация по умолчанию может быть отсутствующей, что объясняет 100% потерю пакетов.
Решение проблем
1. Настройки маршрутизации
Убедитесь, что маршрут для внешних адресов конфигурирован правильно. В вашем случае это должно быть установлено следующим образом:
ip route add 0.0.0.0/1 via <VPN_GATEWAY_IP> dev tun0
ip route add 128.0.0.0/1 via <VPN_GATEWAY_IP> dev tun0
Обратите внимание, что <VPN_GATEWAY_IP>
должен быть IP-адресом, предоставляемым сервером OpenVPN.
2. Применение Kubernetes NetworkPolicy
Вы создали базовую NetworkPolicy, которая разрешает все ingress и egress трафики. Убедитесь, что это не влияет на маршрутизацию. Если требуется более строгая политика, убедитесь, что разрешаются все необходимые порты и разрешен весь трафик через интерфейс tun0
.
3. Использование iptables
Контейнерные сети могут требовать дополнительных правил iptables
, чтобы правильно маршрутизировать трафик из tun0
на eth0
. Убедитесь, что у вас есть необходимые правила, которые разрешают передачу трафика между интерфейсами. Рассмотрите возможность добавления правил, например:
iptables -A FORWARD -i tun0 -j ACCEPT
iptables -A FORWARD -o tun0 -m state --state RELATED,ESTABLISHED -j ACCEPT
4. Поддержка маршрутизации
Также стоит убедиться, что включена IP-маршрутизация в каждом из подов. Проверьте это командой:
sysctl net.ipv4.ip_forward
Если параметр не включен (0
), выполните команду:
sysctl -w net.ipv4.ip_forward=1
5. Тестирование
Проведите тестирование через traceroute
с интерфейса tun0
, чтобы удостовериться, что маршруты настроены правильно. Это позволит визуализировать, где пакеты теряются.
traceroute -i tun0 8.8.8.8
Заключение
Проблема с туннелем tun0
связана с неправильной маршрутизацией в кластере Kubernetes. Применяя описанные шаги, вы сможете успешно настроить маршруты и обеспечить корректное функционирование вашего клиента OpenVPN в подах Kubernetes. Также помните, что правильная настройка сетей в Kubernetes может значительно повлиять на производительность и стабильность ваших приложений.
Попробуйте реализовать предложенные решения и протестировать их, чтобы выявить работоспособность вашего подключения через tun0
.