docs/networking.md:
- Раздел ingress-proxypass: архитектура, пример конфигурации с TLS и auth
- Раздел splitgw: TPROXY-маршрутизация, systemd и k8s режимы, пример TV
- Раздел hysteria2-server: установка на VPS, SSH-пароль, URL для клиентов
docs/make-reference.md:
- addon-mediaserver (с флагом без Hysteria2)
- addon-hysteria2-server (SSH-ключ и интерактивный пароль -k)
- addon-splitgw (systemd и k8s DaemonSet)
- addon-ingress-proxypass
docs/troubleshooting.md:
- Строки таблицы: 502/503/404 для ingress-proxypass, TPROXY для splitgw,
firewall/TLS для hysteria2-server, Prowlarr sidecar для mediaserver
- Разделы диагностики: ingress-proxypass, splitgw, hysteria2-server
с конкретными командами kubectl/systemctl/iptables
9.6 KiB
9.6 KiB
Решение проблем
Таблица проблем
| Проблема | Причина | Решение |
|---|---|---|
Permission denied (publickey) |
Ключ не скопирован | ssh-copy-id user@server |
Vault decryption failed |
Неверный пароль vault | Проверь VAULT_PASSWORD в .env |
| kube-vip VIP не пингуется | Неверный интерфейс | Проверь kube_vip_interface — должен совпадать с ip a на master01 |
| RPi K3S не стартует | Не включены cgroups | `ssh pi@rpi "cat /proc/cgroups |
| PVC в Pending | NFS не монтируется | kubectl get events -A — проверь монтирование NFS на нодах |
ingress EXTERNAL-IP <pending> |
kube-vip не работает | `kubectl -n kube-system get pods |
| etcd нет кворума | Нода упала | Нужно минимум 2 из 3 нод. kubectl get nodes |
| worker01/rpi01 не присоединились | master01 не готов | Убедись что master01 полностью стартовал. serial: 1 гарантирует порядок |
| Kiali: "Could not get token" | Нет Secret | kubectl -n istio-system get secret kiali-admin-token |
| Grafana PVC Pending | NFS StorageClass не default | kubectl get sc — nfs-master01 должен быть (default) |
| Molecule: image pull failed | Нет интернета | docker pull geerlingguy/docker-ubuntu2204-ansible:latest вручную |
| Molecule: idempotency failed | Таск не идемпотентен | Добавь changed_when: false |
ansible-lint ошибки |
Синтаксис | make molecule-lint и исправь файлы |
| etcd restore: снимок не найден | Неверный путь | make etcd-list-snapshots — снимок должен быть на первом мастере |
| add-node: нода не присоединяется | kube-vip не работает | `kubectl -n kube-system get pods |
| remove-node: drain завис | PodDisruptionBudget | kubectl get pdb -A — проверь PDB |
| cert-manager: сертификат Pending | Нет публичного домена | При letsencrypt нужен публичный домен + ingress-nginx |
| Harbor: registry push fails | Неверный externalURL | harbor_ingress_host должен совпадать с реальным hostname |
| Jenkins: агент не стартует | RBAC | kubectl get events -n jenkins — проверь ServiceAccount |
| Vault: sealed после рестарта | Нет auto-unseal | Настрой vault_auto_unseal_type или используй k8s unsealer |
| NetBird: клиент не подключается | DNS не настроен | Настрой A-записи для Management, Signal, Coturn LB IPs |
| MinIO: distributed не поднимается | Мало нод | Distributed требует минимум 4 реплики/ноды |
| Nextcloud: redirect loop | HTTP→HTTPS конфликт | Добавь TRUSTED_PROXIES в конфиг Nextcloud |
| ingress-proxypass: 502 Bad Gateway | Кластер не достигает внешний IP | curl -v http://<external-ip>:<port> с ноды кластера; проверь файрвол на внешнем хосте |
| ingress-proxypass: 503 | Endpoints пустой | kubectl -n ingress-proxypass get endpoints — должны быть адреса |
| ingress-proxypass: 404 | Имя хоста не совпадает | kubectl -n ingress-proxypass describe ingress <name> — хост должен совпасть точно |
| splitgw: трафик не перехватывается | TPROXY mark не применён | iptables -t mangle -L SPLITGW -v -n — должны быть правила; journalctl -u splitgw-rules -f |
| splitgw: sing-box не стартует | Ошибка конфига | journalctl -u singbox -f; sing-box check --config /etc/sing-box/config.json |
| splitgw: YouTube всё равно без VPN | DNS утечка | DNS-запросы должны идти через TPROXY; nslookup youtube.com 8.8.8.8 с устройства |
| hysteria2-server: порт закрыт | Файрвол VPS | ufw allow 443/udp или firewall-cmd --add-port=443/udp --permanent |
| hysteria2-server: клиент не подключается | Самоподписанный сертификат | Добавь insecure=1 в URL или установи tls_mode: acme |
| mediaserver: Prowlarr не видит индексеры | Hysteria2 sidecar упал | kubectl -n mediaserver logs <prowlarr-pod> -c hysteria2 |
Подробный вывод
ANSIBLE_VERBOSITY=2 make install # основной вывод
ANSIBLE_VERBOSITY=4 make install # максимальный вывод
ANSIBLE_VERBOSITY=2 ANSIBLE_TAGS=k3s make install # подробно для k3s
Диагностика нод
make shell # открыть bash в ansible-контейнере
# Внутри контейнера:
ansible all -m ping
ansible all -m shell -a "systemctl status k3s"
ansible k3s_master -m shell -a "k3s kubectl get nodes"
ansible k3s_master -m shell -a "journalctl -u k3s -n 50 --no-pager"
Диагностика кластера
export KUBECONFIG=$(pwd)/kubeconfig
# Общий статус
kubectl get nodes -o wide
kubectl get pods -A | grep -v Running
kubectl get events -A --sort-by='.lastTimestamp' | tail -30
# Ресурсы
kubectl top nodes
kubectl top pods -A --sort-by=cpu
# Конкретный под
kubectl describe pod <pod> -n <namespace>
kubectl logs <pod> -n <namespace> --tail=100 -f
kubectl logs <pod> -n <namespace> --previous # логи предыдущего контейнера
# PVC проблемы
kubectl describe pvc <pvc> -n <namespace>
kubectl get pv
# Ingress проблемы
kubectl describe ingress <name> -n <namespace>
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller -f
Проверка etcd
kubectl -n kube-system exec -it \
$(kubectl -n kube-system get pods -l component=etcd -o name | head -1) \
-- etcdctl --endpoints=https://127.0.0.1:2379 \
--cacert=/var/lib/kubernetes/k3s/server/tls/etcd/server-ca.crt \
--cert=/var/lib/kubernetes/k3s/server/tls/etcd/server-client.crt \
--key=/var/lib/kubernetes/k3s/server/tls/etcd/server-client.key \
member list
Диагностика NFS
# На NFS сервере:
make shell
ansible nfs_server -m shell -a "exportfs -v"
ansible nfs_server -m shell -a "showmount -e localhost"
# На нодах кластера:
ansible k3s_cluster -m shell -a "mount | grep nfs"
ansible k3s_cluster -m shell -a "showmount -e 192.168.1.10"
Диагностика kube-vip
# Статус подов
kubectl -n kube-system get pods -l app.kubernetes.io/name=kube-vip
# Логи
kubectl -n kube-system logs -l app.kubernetes.io/name=kube-vip
# Проверить VIP
ping 192.168.1.100 # kube_vip_address
curl -k https://192.168.1.100:6443/healthz
Диагностика cert-manager
kubectl get certificate -A
kubectl get certificaterequest -A
kubectl get challenges -A
kubectl describe certificate <name> -n <namespace>
kubectl logs -n cert-manager deployment/cert-manager -f
Диагностика ingress-proxypass
# Ресурсы namespace
kubectl -n ingress-proxypass get all,ingress,endpoints
# Проверить Endpoints заполнены (Addresses не должен быть <none>)
kubectl -n ingress-proxypass describe endpoints <name>
# Тест изнутри кластера
kubectl run curl --rm -it --image=curlimages/curl -- \
curl -v http://<service>.ingress-proxypass.svc.cluster.local:<port>
# Проверить что nginx подхватил правила
kubectl -n ingress-nginx logs -l app.kubernetes.io/name=ingress-nginx --tail=50
Диагностика splitgw
# Статус сервисов на хосте gateway
systemctl status singbox splitgw-rules
journalctl -u singbox -f
journalctl -u splitgw-rules -f
# Проверить TPROXY-правила iptables
iptables -t mangle -L SPLITGW -v -n
iptables -t mangle -L PREROUTING -v -n
# Проверить sing-box конфиг
sing-box check --config /etc/sing-box/config.json
# Диагностика DNS (с устройства-источника)
nslookup youtube.com
nslookup vk.com
Диагностика hysteria2-server
# Статус на VPS
systemctl status hysteria2
journalctl -u hysteria2 -f
# Проверить порт открыт (UDP)
ss -ulnp | grep 443
# С клиентской машины:
nc -u <vps-ip> 443
# Тест подключения
curl -v --proxy hysteria2://pass@<vps-ip>:443?insecure=1 https://example.com
Типичные Molecule ошибки
| Ошибка | Решение |
|---|---|
Unable to pull image |
docker pull geerlingguy/docker-ubuntu2204-ansible:latest |
FAILED: assert ... is defined |
Добавь переменную в converge.yml секцию vars: |
Idempotency: CHANGED |
Добавь changed_when: false к таску |
yamllint: wrong indentation |
Исправь отступы, запусти make molecule-lint |
ansible-lint: no-changed-when |
Добавь changed_when: <условие> |
sysctl: Operation not permitted |
Добавь privileged: true в molecule.yml |