Files
DevOpsLab/scripts/portforward.py
Сергей Антропов ebed1f76ab feat: добавлена команда recreate для port-forward
- Добавлена функция recreate_portforwards() в scripts/portforward.py
- Команда recreate удаляет все существующие port-forward и создает их заново
- Добавлена команда в Makefile: make k8s portforward recreate
- Полезно для переподключения после перезапуска контейнера или кластера
2025-10-26 09:28:07 +03:00

210 lines
7.5 KiB
Python
Executable File
Raw 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.

#!/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 recreate_portforwards():
"""Пересоздает port-forward: удаляет существующие и создает заново"""
print("🔄 Пересоздание port-forward...")
clear_portforwards()
time.sleep(1)
create_portforwards()
def main():
if len(sys.argv) < 2:
print("Usage: portforward.py <create|list|delete|clear|recreate> [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 == "recreate":
recreate_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()