From 09d32c8cb1c55c6ace56229c4a7d25611d9dd12e Mon Sep 17 00:00:00 2001 From: erjemin Date: Sat, 29 Mar 2025 17:43:53 +0300 Subject: [PATCH] =?UTF-8?q?add:=20=D0=BF=D0=BE=D0=B4=20=D1=81=203X-UI=20..?= =?UTF-8?q?..?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- kubernetes/k3s-3xui-pod.md | 97 ++++++++++++++++++++++++++++++++++ raspberry-and-orange-pi/k3s.md | 8 +-- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/kubernetes/k3s-3xui-pod.md b/kubernetes/k3s-3xui-pod.md index ee58f80..3254ed2 100644 --- a/kubernetes/k3s-3xui-pod.md +++ b/kubernetes/k3s-3xui-pod.md @@ -220,6 +220,103 @@ sudo kubectl apply -f ~/k3s/vpn/x-ui/deployment.yaml ## Единая точка входа VPN-соединений через под 3x-ui +Под с 3x-ui может быть запущен k3s на произвольном узле, и может быть произвольно перемещён в кластере на другой узел. +Таким образом, если мы хотим предоставить доступ к VPN-соединениям из интернета, нам нужно настроить доступ через +единый IP-адрес. Это можно сделать несколькими способами. +### Доступ через VIP (виртуальный IP) c перенаправлял трафика через Keepalived на узел с подом с 3x-ui +При [развертывании k3s](../raspberry-and-orange-pi/k3s.md) на Orange Pi 5 Plus мы уже настраивали Keepalived. Теперь +надо настроить его так, чтобы узел с подом 3x-ui получал больший приоритет в Keepalived, и тогда виртуальный IP +будет получать трафик с этого узла. + +**Лучшим решением будет динамическая настройка приоритета в Keepalived.** + +Лучший способ — настроить так, чтобы приоритет Keepalived ноды автоматически повышался, если под 3x-ui запущен на ней. +Это можно сделать с помощью механизма `track_script`, который будет проверять наличие пода и динамически менять +приоритет. Такой подход сохранит текущую работу K3s API и [подов Shadowsocks](k3s-shadowsocks-client.md), добавив +поддержку 3x-ui. + +Создадим проверочный скрипт (на каждом узле), который будет проверять наличие пода 3x-ui. Скрипт будет +расположен в `~/scripts/check_xui.sh`: +```bash +mkdir -p ~/scripts +nano ~/scripts/check_xui.sh +``` + +И вставим в него следующий код (на каждой ноде): +```bash +#!/usr/bin/bash +NODE_NAME=$(hostname) # Получаем имя текущей ноды +POD_NAME=$(kubectl get pods -n x-ui -o jsonpath="{.items[?(@.spec.nodeName=='$NODE_NAME')].metadata.name}") +if [ -n "$POD_NAME" ]; then + exit 0 # Под есть на этой ноде +else + exit 1 # Пода нет +fi +``` + +Скрипт использует `kubectl`, чтобы проверить, есть ли под `3x-ui` в _namespace_ `x-ui` на текущей ноде. Использование +`sudo` не требуется, так как скрипт будет запускаться `keepalived`, который работает от `root`. +Убедись, что kubectl доступен на всех нодах и настроен для работы с кластером (например, через kubeconfig). + +Сделаем скрипт исполняемым (на каждой ноде): +```bash +sudo chmod +x ~/scripts/check_xui.sh +``` + +Обновим конфиг `reepalived`, добавив `vrrp_script` и привязку к нему через `track_script`. Теперь мы переведем все +ноды в **BACKUP** (чтобы избежать конфликтов), а приоритет будет динамически меняться в зависимости от наличия пода. + +На перовой мастер-ноде: +```bash +sudo nano /etc/keepalived/keepalived.conf +``` + +И теперь там будет вот такой конфиг (не забудь указать правильное имя пользователя `` в пути к скрипту): +```text +```pycon +vrrp_script check_xui { + script "/home//scripts/check_xui.sh" + interval 2 # Проверять каждые 2 секунды + weight 50 # Добавить 50 к приоритету, если под есть +} + +vrrp_instance VI_1 { + # state MASTER + state BACKUP # Все ноды стартуют как BACKUP + interface enP4p65s0 + virtual_router_id 51 + priority 100 # Базовый приоритет + advert_int 1 + unicast_src_ip 192.168.1.26 + unicast_peer { + 192.168.1.27 + 192.168.1.28 + } + virtual_ipaddress { + 192.168.1.200 + } + track_script { + check_xui # Привязка к скрипту + } +} +``` + +Перезапустим Keepalived: +```bash +sudo service keepalived restart +``` + +Аналогичным образом настроим конфиги на других узлах (добавить блок `vrrp_script` сверху, и добавить `track_script` в +`vrrp_instance`). Не забудь указать проверить `unicast_src_ip` для каждой ноды и перезапустить Keepalived на всех узлах. + +Теперь на каждой ноде cкрипт `~/scripts/check_xui.sh` проверяет наличие пода `x-ui` каждые 2 секунды. Если под есть, +Keepalived добавляет 50 к базовому приоритету ноды (например, 100 → 150). Если пода нет, приоритет остаётся базовым +(100, 90 или 80). Нода с наивысшим приоритетом становится MASTER и получает виртуальный IP. Таким образом, VIP всегда +будет указывать на ноду с подом 3x-ui. + +Теперь панель 3x-ui будет доступна с виртуального IP (192.168.1.200). Все VPN-соединения будут работать через него. +Так что если на домашнем роутере настроить перенаправление портов (для 2053-порта веб-панели 3x-ui, и портов которые +будем выбирать для VPN-соединений), то можно будет подключаться к 3x-ui и VPN-соединениям из любой точки мира. diff --git a/raspberry-and-orange-pi/k3s.md b/raspberry-and-orange-pi/k3s.md index bfad517..f3e6a0f 100644 --- a/raspberry-and-orange-pi/k3s.md +++ b/raspberry-and-orange-pi/k3s.md @@ -499,6 +499,8 @@ rpi3b Ready 27s v1.31.6+k3s1 не сработает. Выходом может стать использование воркер-узлов во внешнем интернете. Идея в том, что если какой-нибудь URL не получится обработать на поде одного узла, то можно попробовать обработать его на другом узле, в другой локации. +#### Настройка Keepalived + Так как узлы k3s взаимодействуют через API на 6443-порте, то для доступа к кластеру из внешнего интернета нужно будет обеспечить проброс трафика через роутер сети на один из мастер-узлов. НО у нас три мастер-узла, а значит если упадет узел на который происходит проброс, то удаленный воркер-узел "отвелится" и потеряет доступ к кластеру. Объединить @@ -519,7 +521,7 @@ sudo nano /etc/keepalived/keepalived.conf ``` На первом мастер-узле (хост — `opi5plus-1`, IP — `192.168.1.26`): -```text +```pycon vrrp_instance VI_1 { state MASTER # ЭТО ГЛАВНЫЙ ХОСТ. ПО УМОЛЧАНИЮ ТРАФИК С VIP БУДЕТ ПЕРЕНАПРАВЛЯТЬСЯ НА ЭТОТ ХОСТ interface enP4p65s0 # У Orange Pi 5 plus два интерфейса, и хост подключен по интерфейсу enP4p65s0 @@ -538,7 +540,7 @@ vrrp_instance VI_1 { ``` На втором мастер-узле (хост — `opi5plus-2`, IP — `192.168.1.27`): -```text +```pycon vrrp_instance VI_1 { state BACKUP # ЭТО ВТОРОЙ ХОСТ. ОН БУДЕТ ПОЛУЧАТЬ ТРАФИК С VIP, ЕСЛИ ГЛАВНЫЙ ХОСТ УПАДЕТ interface enP4p65s0 # У Orange Pi 5 plus два интерфейса, и хост подключен по интерфейсу enP4p65s0 @@ -557,7 +559,7 @@ vrrp_instance VI_1 { ``` И, наконец, на третьем мастер-узле (хост — `opi5plus-3`, IP — `192.168.1.28`): -```text +```pycon vrrp_instance VI_1 { state BACKUP # ЭТО ТРЕТИЙ ХОСТ. ОН БУДЕТ ПОЛУЧАТЬ ТРАФИК С VIP, ЕСЛИ ГЛАВНЫЙ- И БЭКАП-ХОСТ УПАДЕТ interface enP4p65s0 # У Orange Pi 5 plus два интерфейса, и этот узел подключен по enP4p65s0