Files
K3S/docs/networking.md
Sergey Antropoff 5079975d5e feat: добавить аддон ingress-add-domains — добавить домены к сервисам кластера
Helm chart + Ansible роль, создающие Ingress-only правила для уже существующих
K8s сервисов. Каждый Ingress создаётся в namespace целевого сервиса.

Поддерживает: TLS (cert-manager или готовый Secret), basic auth (автохэш пароля
через openssl passwd -apr1), WebSocket, несколько хостов, per-entry аннотации.
2026-04-26 12:02:41 +03:00

394 lines
10 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Сеть и доступ
## ingress-nginx
HTTP/S Ingress controller, точка входа для всех веб-приложений кластера. Подробнее: [addons/ingress-nginx/README.md](../addons/ingress-nginx/README.md).
```yaml
addon_ingress_nginx: true
ingress_nginx_load_balancer_ip: "" # авто от kube-vip
```
Базовый Ingress:
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-app
annotations:
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
ingressClassName: nginx
tls:
- hosts: [myapp.example.com]
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: my-app
port:
number: 80
```
---
## cert-manager — TLS сертификаты
Автоматические TLS сертификаты от Let's Encrypt или самоподписанного CA. Подробнее: [addons/cert-manager/README.md](../addons/cert-manager/README.md).
```yaml
addon_cert_manager: true
cert_manager_issuer: "letsencrypt"
cert_manager_acme_email: "admin@example.com"
```
---
## Istio — Service Mesh
mTLS между сервисами, traffic management, observability. Подробнее: [addons/istio/README.md](../addons/istio/README.md).
```yaml
addon_istio: true
istio_mtls_mode: "STRICT"
kiali_enabled: true
```
### Включить sidecar injection
```bash
kubectl label namespace my-app istio-injection=enabled
```
### VirtualService routing
```yaml
apiVersion: networking.istio.io/v1alpha3
kind: VirtualService
metadata:
name: my-app
spec:
hosts: ["myapp.local"]
gateways: ["istio-system/istio-ingressgateway"]
http:
- route:
- destination:
host: my-app
port:
number: 80
```
---
## NetBird VPN
Self-hosted WireGuard VPN с управляемым сервером. Клиенты из любой точки мира получают доступ к подсетям кластера. Подробнее: [addons/netbird/README.md](../addons/netbird/README.md).
### Быстрый старт
```yaml
addon_netbird: true
netbird_domain: "netbird.example.com"
# Subnet Router — доступ к локальной сети из VPN
netbird_subnet_router_enabled: true
netbird_subnet_routes:
- "192.168.1.0/24" # локальная сеть
- "10.42.0.0/16" # pod CIDR
- "10.43.0.0/16" # service CIDR
# Exit Node — интернет через кластер
netbird_exit_node_enabled: false
```
### Архитектура
```
VPN Client
│ WireGuard
├──→ Management (gRPC LoadBalancer IP)
├──→ Signal (WebRTC signaling)
└──→ Coturn (STUN/TURN для NAT traversal)
└──→ Subnet Router Pod ──→ 192.168.1.0/24
└──→ 10.42.0.0/16 (pods)
```
### Подключение клиентов
```bash
netbird up --management-url grpc://netbird.example.com:80
```
---
## ingress-add-domains — добавить домены к сервисам кластера
Позволяет быстро открыть дополнительные домены для уже существующих K8s сервисов без изменения их шаблонов. Создаёт **только Ingress** в namespace целевого сервиса. Подробнее: [addons/ingress-add-domains/README.md](../addons/ingress-add-domains/README.md).
```yaml
# group_vars/all/addons.yml
addon_ingress_add_domains: true
ingress_add_domains_entries:
# Внутренний домен без TLS
- name: gitea-local
hosts: [gitea.local]
service:
name: gitea-http
namespace: gitea
port: 3000
# Внешний домен с TLS + basic auth
- name: grafana-home
hosts: [grafana.home.ru]
service:
name: prometheus-stack-grafana
namespace: monitoring
port: 80
tls:
enabled: true
certManager:
enabled: true
issuer: letsencrypt-prod
auth:
enabled: true
username: admin
password: "{{ vault_grafana_proxy_password }}"
```
```bash
make addon-ingress-add-domains
```
| Сценарий | Инструмент |
|---|---|
| Открыть K8s-сервис по новому домену | **ingress-add-domains** |
| Проксировать сервис вне кластера (по IP) | ingress-proxypass |
---
## ingress-proxypass — проксировать внешние сервисы
Позволяет открыть по домену любой сервис, работающий **вне кластера** (роутер, NAS, Plex на отдельной машине и т.д.), через тот же ingress-nginx VIP. Для каждой записи создаётся: `Service (ClusterIP, без selector)` + `Endpoints` + `Ingress`. Подробнее: [addons/ingress-proxypass/README.md](../addons/ingress-proxypass/README.md).
```yaml
# group_vars/all/addons.yml
addon_ingress_proxypass: true
ingress_proxypass_proxies:
- name: router
hosts: [router.home.ru]
ips: [192.168.1.1]
port: 8080
- name: nas
hosts: [nas.home.ru]
ips: [192.168.1.20]
port: 5000
tls:
enabled: true
secretName: wildcard-tls
- name: grafana-ext
hosts: [grafana.home.ru]
ips: [192.168.1.60]
port: 3000
auth:
enabled: true
username: admin
password: "{{ vault_proxy_password }}" # хэш генерируется автоматически
```
```bash
make addon-ingress-proxypass
```
Маршрут трафика: `kube-vip VIP → ingress-nginx → Service → Endpoints → внешний IP:PORT`
---
## splitgw — прозрачный split-tunnel gateway
Устанавливает `sing-box` с TPROXY-перехватом на хосте или K3S DaemonSet. Трафик с указанных устройств (Smart TV и т.п.) маршрутизируется по правилам: YouTube/Google → Hysteria2 VPN, RU-сервисы и частные сети → прямой маршрут. Подробнее: [addons/splitgw/README.md](../addons/splitgw/README.md).
```yaml
# group_vars/all/addons.yml (+ group [splitgw] в inventory)
addon_splitgw: true
splitgw_tv_sources:
- "192.168.1.100/32" # Smart TV
splitgw_router_ip: "192.168.1.1"
# vault_hysteria2_url задаётся в vault.yml
```
```bash
# Режим systemd на хосте (по умолчанию):
make addon-splitgw
# Режим K8s DaemonSet:
make addon-splitgw ARGS="-e splitgw_deploy_mode=k8s"
```
Маршрут: `Smart TV → шлюз splitgw (TPROXY:7893) → sing-box → YouTube/Google: Hysteria2 VPN | остальное: прямой`
---
## hysteria2-server — VPN-сервер на удалённом VPS
Устанавливает Hysteria2-сервер на внешний VPS (не часть кластера). Сервер нужен для `splitgw` и `mediaserver` (Prowlarr sidecar). Подробнее: [addons/hysteria2-server/README.md](../addons/hysteria2-server/README.md).
```yaml
# inventory/hosts.ini
[hysteria2_server]
myvps ansible_host=1.2.3.4 ansible_user=root
# group_vars/all/vault.yml
vault_hysteria2_server_password: "мойпароль"
```
```bash
# По SSH-ключу:
make addon-hysteria2-server
# По SSH-паролю (интерактивный ввод):
make addon-hysteria2-server ARGS="-k"
```
После установки выводится готовая URL-строка для Shadowrocket / NekoBox / Hiddify:
```
hysteria2://пароль@1.2.3.4:443?insecure=1#MyVPS
```
---
## kube-vip LoadBalancer
kube-vip обрабатывает все `LoadBalancer` сервисы — каждый сервис с `type: LoadBalancer` автоматически получает IP из подсети кластера.
```yaml
apiVersion: v1
kind: Service
metadata:
name: my-tcp-service
annotations:
kube-vip.io/loadbalancerIPs: "192.168.1.150" # статический IP (опционально)
spec:
type: LoadBalancer
ports:
- port: 8080
targetPort: 8080
selector:
app: my-app
```
---
## DNS внутри кластера
Паттерны DNS для сервисов:
```
<service>.<namespace>.svc.cluster.local
# Примеры:
postgresql.postgresql.svc.cluster.local:5432
minio.minio.svc.cluster.local:9000
vault.vault.svc.cluster.local:8200
loki.loki.svc.cluster.local:3100
smtp-relay.smtp-relay.svc.cluster.local:25
tempo.tempo.svc.cluster.local:4317
```
---
## Network Policies (Calico/Cilium)
Требует `k3s_cni: "calico"` или `k3s_cni: "cilium"`.
```yaml
# Запретить весь трафик в namespace:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: default-deny-all
namespace: my-app
spec:
podSelector: {}
policyTypes: [Ingress, Egress]
---
# Разрешить только из ingress-nginx:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-ingress
namespace: my-app
spec:
podSelector:
matchLabels:
app: my-app
ingress:
- from:
- namespaceSelector:
matchLabels:
kubernetes.io/metadata.name: ingress-nginx
ports:
- port: 8080
---
# Разрешить DNS (CoreDNS):
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: allow-dns
namespace: my-app
spec:
podSelector: {}
egress:
- ports:
- port: 53
protocol: UDP
- port: 53
protocol: TCP
```
---
## Cilium — дополнительные возможности
```yaml
k3s_cni: "cilium"
cilium_hubble_enabled: true # observability
cilium_hubble_ui_enabled: false # Hubble UI
```
L7 Network Policy (только Cilium):
```yaml
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
name: allow-http-get
spec:
endpointSelector:
matchLabels:
app: my-api
ingress:
- fromEndpoints:
- matchLabels:
app: frontend
toPorts:
- ports:
- port: "8080"
protocol: TCP
rules:
http:
- method: GET
path: "/api/.*"
```