feat: добавлен port-forward для кластера Kubernetes
- Создан скрипт scripts/portforward.py для управления port-forward - Добавлены команды в Makefile: - make k8s portforward create - создать port-forward для всех сервисов - make k8s portforward list - показать активные port-forward - make k8s portforward clear - очистить все port-forward - make k8s portforward delete PORT - удалить конкретный port-forward - Сервисы остаются с типом ClusterIP - Port-forward автоматически создается для Prometheus, Grafana, Kiali и Metrics Server - Порты: Prometheus 9090, Grafana 3000, Kiali 20001, Metrics Server 4443
This commit is contained in:
200
scripts/portforward.py
Executable file
200
scripts/portforward.py
Executable file
@@ -0,0 +1,200 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Скрипт для управления port-forward для Kubernetes сервисов
|
||||
Автор: Сергей Антропов
|
||||
Сайт: https://devops.org.ru
|
||||
"""
|
||||
import sys
|
||||
import yaml
|
||||
import subprocess
|
||||
import os
|
||||
import signal
|
||||
import time
|
||||
|
||||
def get_cluster_name():
|
||||
"""Получаем имя кластера из preset файла"""
|
||||
preset_file = "molecule/presets/k8s/kubernetes.yml"
|
||||
with open(preset_file, 'r') as f:
|
||||
preset = yaml.safe_load(f)
|
||||
return preset['kind_clusters'][0]['name']
|
||||
|
||||
def run_cmd(cmd):
|
||||
"""Выполняет команду и возвращает результат"""
|
||||
print(f"[run] {cmd}")
|
||||
result = subprocess.run(cmd, shell=True, capture_output=True, text=True)
|
||||
if result.returncode != 0:
|
||||
print(f"[error] {result.stderr}")
|
||||
else:
|
||||
print(result.stdout)
|
||||
return result
|
||||
|
||||
def get_portforward_pids():
|
||||
"""Получает PID процессов port-forward"""
|
||||
result = subprocess.run("ps aux | grep 'kubectl.*port-forward' | grep -v grep", shell=True, capture_output=True, text=True)
|
||||
pids = []
|
||||
for line in result.stdout.split('\n'):
|
||||
if line.strip():
|
||||
pids.append(int(line.split()[1]))
|
||||
return pids
|
||||
|
||||
def list_portforwards():
|
||||
"""Показывает список всех активных port-forward"""
|
||||
pids = get_portforward_pids()
|
||||
if not pids:
|
||||
print("❌ Нет активных port-forward")
|
||||
return
|
||||
|
||||
print("📋 Активные port-forward:")
|
||||
result = subprocess.run("ps aux | grep 'kubectl.*port-forward' | grep -v grep", shell=True, capture_output=True, text=True)
|
||||
for line in result.stdout.split('\n'):
|
||||
if line.strip():
|
||||
print(f" {line}")
|
||||
|
||||
def clear_portforwards():
|
||||
"""Завершает все процессы port-forward"""
|
||||
pids = get_portforward_pids()
|
||||
if not pids:
|
||||
print("❌ Нет активных port-forward")
|
||||
return
|
||||
|
||||
print(f"🗑️ Завершение {len(pids)} процессов port-forward...")
|
||||
for pid in pids:
|
||||
try:
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
print(f"✅ Процесс {pid} завершен")
|
||||
except ProcessLookupError:
|
||||
print(f"⚠️ Процесс {pid} уже не существует")
|
||||
|
||||
# Ждем завершения процессов
|
||||
time.sleep(2)
|
||||
|
||||
# Принудительно убиваем оставшиеся
|
||||
remaining_pids = get_portforward_pids()
|
||||
if remaining_pids:
|
||||
print("⚠️ Принудительное завершение оставшихся процессов...")
|
||||
for pid in remaining_pids:
|
||||
try:
|
||||
os.kill(pid, signal.SIGKILL)
|
||||
print(f"✅ Процесс {pid} принудительно завершен")
|
||||
except ProcessLookupError:
|
||||
pass
|
||||
|
||||
def create_portforwards():
|
||||
"""Создает port-forward для всех сервисов из preset"""
|
||||
# Загружаем preset
|
||||
preset_file = "molecule/presets/k8s/kubernetes.yml"
|
||||
with open(preset_file, 'r') as f:
|
||||
preset = yaml.safe_load(f)
|
||||
|
||||
cluster_name = preset['kind_clusters'][0]['name']
|
||||
addon_ports = preset['kind_clusters'][0].get('addon_ports', {})
|
||||
|
||||
print(f"🔌 Создание port-forward для кластера: {cluster_name}")
|
||||
|
||||
# Prometheus
|
||||
if addon_ports.get('prometheus'):
|
||||
port = addon_ports['prometheus']
|
||||
print(f" - Prometheus: localhost:{port} -> monitoring/monitoring-kube-prometheus-prometheus:9090")
|
||||
subprocess.Popen([
|
||||
"kubectl",
|
||||
"--server=https://{}-control-plane:6443".format(cluster_name),
|
||||
"--insecure-skip-tls-verify",
|
||||
"port-forward",
|
||||
"-n", "monitoring",
|
||||
"svc/monitoring-kube-prometheus-prometheus",
|
||||
f"{port}:9090"
|
||||
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
# Grafana
|
||||
if addon_ports.get('grafana'):
|
||||
port = addon_ports['grafana']
|
||||
print(f" - Grafana: localhost:{port} -> monitoring/monitoring-grafana:80")
|
||||
subprocess.Popen([
|
||||
"kubectl",
|
||||
"--server=https://{}-control-plane:6443".format(cluster_name),
|
||||
"--insecure-skip-tls-verify",
|
||||
"port-forward",
|
||||
"-n", "monitoring",
|
||||
"svc/monitoring-grafana",
|
||||
f"{port}:80"
|
||||
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
# Kiali
|
||||
if addon_ports.get('kiali'):
|
||||
port = addon_ports['kiali']
|
||||
print(f" - Kiali: localhost:{port} -> istio-system/kiali:20001")
|
||||
subprocess.Popen([
|
||||
"kubectl",
|
||||
"--server=https://{}-control-plane:6443".format(cluster_name),
|
||||
"--insecure-skip-tls-verify",
|
||||
"port-forward",
|
||||
"-n", "istio-system",
|
||||
"svc/kiali",
|
||||
f"{port}:20001"
|
||||
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
# Metrics Server
|
||||
if addon_ports.get('metrics_server'):
|
||||
port = addon_ports['metrics_server']
|
||||
print(f" - Metrics Server: localhost:{port} -> kube-system/metrics-server:4443")
|
||||
subprocess.Popen([
|
||||
"kubectl",
|
||||
"--server=https://{}-control-plane:6443".format(cluster_name),
|
||||
"--insecure-skip-tls-verify",
|
||||
"port-forward",
|
||||
"-n", "kube-system",
|
||||
"svc/metrics-server",
|
||||
f"{port}:4443"
|
||||
], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
|
||||
|
||||
time.sleep(2)
|
||||
print("✅ Port-forward создан")
|
||||
list_portforwards()
|
||||
|
||||
def delete_portforward(port):
|
||||
"""Удаляет port-forward для конкретного порта"""
|
||||
pids = get_portforward_pids()
|
||||
if not pids:
|
||||
print(f"❌ Нет активных port-forward на порту {port}")
|
||||
return
|
||||
|
||||
# Находим процесс с нужным портом
|
||||
result = subprocess.run(f"ps aux | grep 'kubectl.*port-forward.*:{port}' | grep -v grep", shell=True, capture_output=True, text=True)
|
||||
if not result.stdout.strip():
|
||||
print(f"❌ Не найден port-forward на порту {port}")
|
||||
return
|
||||
|
||||
# Извлекаем PID
|
||||
pid = int(result.stdout.split()[1])
|
||||
print(f"🗑️ Завершение port-forward на порту {port} (PID: {pid})...")
|
||||
try:
|
||||
os.kill(pid, signal.SIGTERM)
|
||||
print(f"✅ Port-forward на порту {port} завершен")
|
||||
except ProcessLookupError:
|
||||
print(f"⚠️ Процесс {pid} уже не существует")
|
||||
|
||||
def main():
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: portforward.py <create|list|delete|clear> [port]")
|
||||
sys.exit(1)
|
||||
|
||||
command = sys.argv[1]
|
||||
|
||||
if command == "create":
|
||||
create_portforwards()
|
||||
elif command == "list":
|
||||
list_portforwards()
|
||||
elif command == "clear":
|
||||
clear_portforwards()
|
||||
elif command == "delete":
|
||||
if len(sys.argv) < 3:
|
||||
print("Usage: portforward.py delete <port>")
|
||||
sys.exit(1)
|
||||
port = sys.argv[2]
|
||||
delete_portforward(port)
|
||||
else:
|
||||
print(f"❌ Неизвестная команда: {command}")
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user