Multi-cluster dependency mapping, real-time network monitoring, impact analysis, and CI/CD integration capabilities. Made-with: Cursor
17 KiB
Cluster Connection Manager - Refactoring Plan
✅ TAMAMLANDI - 23 Aralık 2025
Bu refactoring planı başarıyla tamamlandı. Tüm fazlar uygulandı ve mevcut fonksiyonellik korunarak, merkezi bir ClusterConnectionManager mimarisine geçildi.
Executive Summary
Bu plan, mevcut dağınık cluster bağlantı yönetimini merkezi bir ClusterConnectionManager servisine taşımayı amaçlar. Mevcut fonksiyonellik korunarak, aşamalı bir geçiş yapılacaktır.
1. ETKİ ANALİZİ
1.1 Mevcut Servisler ve Sorumlulukları
| Servis | Dosya | Sorumluluk | Kullanım |
|---|---|---|---|
cluster_info_service |
services/cluster_info_service.py |
Remote K8s API erişimi (token/kubeconfig) | clusters.py, cluster_cache_service.py |
cluster_manager_client |
grpc_clients/cluster_manager_client.py |
In-cluster gRPC (cluster-manager pod) | clusters.py, cluster_cache_service.py, namespaces.py |
cluster_cache_service |
services/cluster_cache_service.py |
Redis cache layer | namespaces.py, clusters.py |
kubernetes_service |
services/kubernetes_service.py |
Cluster CRUD, connection test | clusters.py |
1.2 Fonksiyon Kullanım Haritası
┌─────────────────────────────────────────────────────────────────────────────┐
│ ROUTER LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ clusters.py │
│ ├── sync_cluster_data() │
│ │ ├── cluster_manager_client.get_cluster_info() [in-cluster] │
│ │ ├── cluster_info_service.get_cluster_info() [remote] │
│ │ ├── cluster_manager_client.check_gadget_health() [in-cluster] │
│ │ └── cluster_info_service.check_gadget_health() [remote] │
│ │ │
│ ├── get_cluster() → [line 1509-1540] │
│ │ ├── cluster_manager_client.get_cluster_info() [in-cluster] │
│ │ ├── cluster_info_service.get_cluster_info() [remote] │
│ │ └── cluster_manager_client.check_gadget_health() │
│ │ │
│ └── test_cluster_connection() │
│ ├── cluster_manager_client.get_cluster_info() [in-cluster] │
│ ├── cluster_info_service.get_cluster_info() [token/kubeconfig] │
│ ├── cluster_manager_client.check_gadget_health() [in-cluster] │
│ └── Direct HTTP to gadget_endpoint [remote] *YENİ EKLENDİ* │
│ │
│ namespaces.py │
│ ├── get_namespaces() → cluster_cache_service.get_namespaces() │
│ ├── get_deployments() → cluster_cache_service.get_deployments() │
│ ├── get_pods() → cluster_cache_service.get_pods() │
│ ├── get_labels() → cluster_cache_service.get_labels() │
│ └── get_services() → cluster_manager_client.list_services() [direct] │
│ │
│ workloads.py │
│ └── get_workloads() → Database only (no K8s API) │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────────────────┐
│ SERVICE LAYER │
├─────────────────────────────────────────────────────────────────────────────┤
│ │
│ cluster_cache_service.py │
│ ├── get_cluster_info() │
│ │ ├── cluster_info_service.get_cluster_info() [remote] │
│ │ └── cluster_manager_client.get_cluster_info() [in-cluster] │
│ │ │
│ ├── get_namespaces() │
│ │ ├── cluster_info_service.get_namespaces() [remote] │
│ │ └── cluster_manager_client.list_namespaces() [in-cluster] │
│ │ │
│ ├── get_deployments() │
│ │ ├── cluster_info_service.get_deployments() [remote] │
│ │ └── cluster_manager_client.list_deployments() [in-cluster] │
│ │ │
│ ├── get_pods() │
│ │ └── cluster_manager_client.list_pods() [both - TODO: add remote] │
│ │ │
│ ├── get_labels() │
│ │ ├── cluster_info_service.get_labels() [remote] │
│ │ └── cluster_manager_client.get_labels() [in-cluster] │
│ │ │
│ └── get_gadget_health() │
│ └── cluster_manager_client.check_gadget_health() [in-cluster only!] │
│ │
└─────────────────────────────────────────────────────────────────────────────┘
1.3 Kritik Bağımlılıklar
| Bağımlılık | Risk | Etki |
|---|---|---|
cluster_manager_client gRPC proto |
YÜKSEK | Proto değişirse tüm in-cluster çağrılar bozulur |
cluster_info_service K8s client |
ORTA | Token/kubeconfig geçersizse remote cluster erişimi yok |
| Redis cache | DÜŞÜK | Cache yoksa sadece performans düşer |
| PostgreSQL credentials | YÜKSEK | Şifreli token/cert okunamazsa remote erişim yok |
1.4 Eksiklikler (Mevcut Sistem)
- ❌
cluster_cache_service.get_pods()- Remote cluster içincluster_info_service.get_pods()YOK - ❌
cluster_cache_service.get_gadget_health()- Remote cluster desteği YOK - ❌
namespaces.py/get_services()- Remote cluster desteği YOK - ❌ Connection pooling YOK
- ❌ Credential refresh/rotation YOK
- ❌ Circuit breaker YOK
2. REFACTORING PLANI
Faz 0: Hazırlık (Mevcut Kodu Stabilize Et)
Süre: 30 dakika
- Mevcut test connection düzeltmesi (gadget HTTP)
- Eksik
get_pods()metodunucluster_info_service'e ekle - Eksik
get_services()metodunucluster_info_service'e ekle - Remote gadget health check metodunu
cluster_info_service'e ekle
Faz 1: ClusterConnectionManager Skeleton
Süre: 1 saat
Yeni dosya: backend/services/cluster_connection_manager.py
class ClusterConnectionManager:
"""
Unified cluster connection manager.
Single entry point for all cluster operations.
"""
# Connection Management
async def get_connection(cluster_id: int) -> ClusterConnection
async def test_connection(config: ConnectionConfig) -> TestResult
async def close_connection(cluster_id: int)
async def close_all()
# Cluster Info
async def get_cluster_info(cluster_id: int) -> ClusterInfo
async def get_namespaces(cluster_id: int) -> List[Namespace]
async def get_deployments(cluster_id: int, namespace: str) -> List[Deployment]
async def get_pods(cluster_id: int, namespace: str) -> List[Pod]
async def get_services(cluster_id: int, namespace: str) -> List[Service]
async def get_labels(cluster_id: int, namespace: str) -> List[Label]
# Gadget
async def check_gadget_health(cluster_id: int) -> GadgetHealth
# Health Monitoring
async def health_check_all() -> Dict[int, HealthStatus]
Faz 2: ClusterConnection Abstraction
Süre: 1.5 saat
Yeni dosya: backend/services/connections/base.py
class ClusterConnection(ABC):
"""Abstract base for cluster connections"""
@abstractmethod
async def get_k8s_client(self) -> ApiClient
@abstractmethod
async def get_cluster_info(self) -> ClusterInfo
@abstractmethod
async def check_gadget_health(self) -> GadgetHealth
Yeni dosya: backend/services/connections/in_cluster.py
class InClusterConnection(ClusterConnection):
"""Uses cluster-manager gRPC"""
def __init__(self):
self._grpc_client = cluster_manager_client
Yeni dosya: backend/services/connections/remote_token.py
class RemoteTokenConnection(ClusterConnection):
"""Direct K8s API with token auth"""
def __init__(self, api_url, token, ca_cert, skip_tls):
self._config = self._create_config()
Faz 3: Mevcut Servisleri Adapter Pattern ile Wrap Et
Süre: 1 saat
# cluster_connection_manager.py
class ClusterConnectionManager:
def __init__(self):
self._connections: Dict[int, ClusterConnection] = {}
# Wrap existing services (backward compatibility)
self._cluster_info_service = cluster_info_service
self._cluster_manager_client = cluster_manager_client
ÖNEMLİ: Bu aşamada mevcut servisler DEĞİŞTİRİLMEZ, sadece wrap edilir.
Faz 4: Router Migration (Aşamalı)
Süre: 2 saat
4.1 clusters.py Güncellemesi
# ÖNCE (mevcut)
cluster_info = await cluster_info_service.get_cluster_info(...)
# SONRA (yeni)
cluster_info = await cluster_connection_manager.get_cluster_info(cluster_id)
4.2 namespaces.py Güncellemesi
# ÖNCE (mevcut)
services = await cluster_manager_client.list_services(...)
# SONRA (yeni)
services = await cluster_connection_manager.get_services(cluster_id, namespace)
Faz 5: Cache Service Integration
Süre: 1 saat
cluster_cache_service.py → ClusterConnectionManager kullanacak şekilde güncelle:
# ÖNCE
if self._is_remote_cluster(connection_info):
data = await cluster_info_service.get_cluster_info(...)
else:
data = await cluster_manager_client.get_cluster_info(...)
# SONRA
data = await cluster_connection_manager.get_cluster_info(cluster_id)
Faz 6: Health Monitoring (Background Task)
Süre: 1 saat
# backend/services/health/cluster_health_monitor.py
class ClusterHealthMonitor:
"""Background task for periodic health checks"""
async def start(self):
while True:
await self._check_all_clusters()
await asyncio.sleep(HEALTH_CHECK_INTERVAL)
async def _check_all_clusters(self):
clusters = await self._get_active_clusters()
for cluster in clusters:
try:
health = await cluster_connection_manager.check_gadget_health(cluster.id)
await self._update_health_status(cluster.id, health)
except Exception as e:
logger.error("Health check failed", cluster_id=cluster.id, error=str(e))
Faz 7: Cleanup ve Deprecation
Süre: 30 dakika
- Eski servisleri deprecated olarak işaretle
- Import warning'leri ekle
- Dokümantasyon güncelle
3. DOSYA YAPISI (SONUÇ)
backend/
├── services/
│ ├── cluster_connection_manager.py # YENİ - Merkezi Manager
│ ├── connections/ # YENİ - Connection implementations
│ │ ├── __init__.py
│ │ ├── base.py # Abstract base class
│ │ ├── in_cluster.py # InClusterConnection
│ │ ├── remote_token.py # RemoteTokenConnection
│ │ └── remote_kubeconfig.py # RemoteKubeconfigConnection
│ ├── health/ # YENİ - Health monitoring
│ │ ├── __init__.py
│ │ └── cluster_health_monitor.py
│ │
│ ├── cluster_info_service.py # MEVCUT - Deprecate sonra
│ ├── cluster_cache_service.py # MEVCUT - Güncelle
│ ├── kubernetes_service.py # MEVCUT - Koru
│ └── event_service.py # MEVCUT - Değişmez
│
├── grpc_clients/
│ └── cluster_manager_client.py # MEVCUT - Internal kullanım
│
└── routers/
├── clusters.py # Güncelle
└── namespaces.py # Güncelle
4. MİGRASYON TABLOSU
| Mevcut Çağrı | Yeni Çağrı | Dosya |
|---|---|---|
cluster_info_service.get_cluster_info() |
ccm.get_cluster_info() |
clusters.py |
cluster_manager_client.get_cluster_info() |
ccm.get_cluster_info() |
clusters.py |
cluster_info_service.check_gadget_health() |
ccm.check_gadget_health() |
clusters.py |
cluster_manager_client.check_gadget_health() |
ccm.check_gadget_health() |
clusters.py, cache |
cluster_info_service.get_namespaces() |
ccm.get_namespaces() |
cache |
cluster_manager_client.list_namespaces() |
ccm.get_namespaces() |
cache |
cluster_info_service.get_deployments() |
ccm.get_deployments() |
cache |
cluster_manager_client.list_deployments() |
ccm.get_deployments() |
cache |
cluster_manager_client.list_pods() |
ccm.get_pods() |
cache |
cluster_info_service.get_labels() |
ccm.get_labels() |
cache |
cluster_manager_client.get_labels() |
ccm.get_labels() |
cache |
cluster_manager_client.list_services() |
ccm.get_services() |
namespaces.py |
5. RİSK YÖNETİMİ
5.1 Rollback Stratejisi
Her faz için rollback:
- Faz 1-3: Yeni dosyaları sil, import'ları kaldır
- Faz 4-5: Git revert ile eski router/service koduna dön
- Faz 6: Background task'ı devre dışı bırak
5.2 Test Stratejisi
Her faz sonrası test:
- ✅ In-cluster connection çalışıyor mu?
- ✅ Remote token connection çalışıyor mu?
- ✅ Cache çalışıyor mu?
- ✅ Gadget health check çalışıyor mu?
- ✅ UI cluster listesi yükleniyor mu?
- ✅ UI test connection çalışıyor mu?
5.3 Fallback Mekanizması
class ClusterConnectionManager:
async def get_cluster_info(self, cluster_id: int):
try:
# Yeni yöntem
connection = await self.get_connection(cluster_id)
return await connection.get_cluster_info()
except Exception as e:
# Fallback: Eski yöntem
logger.warning("Falling back to legacy service", error=str(e))
return await self._legacy_get_cluster_info(cluster_id)
6. UYGULAMA TAKVİMİ
| Faz | Görev | Süre | Kümülatif |
|---|---|---|---|
| 0 | Hazırlık - Eksik metodları ekle | 30 dk | 30 dk |
| 1 | ClusterConnectionManager skeleton | 1 saat | 1.5 saat |
| 2 | Connection abstractions | 1.5 saat | 3 saat |
| 3 | Adapter pattern wrap | 1 saat | 4 saat |
| 4 | Router migration | 2 saat | 6 saat |
| 5 | Cache service integration | 1 saat | 7 saat |
| 6 | Health monitoring | 1 saat | 8 saat |
| 7 | Cleanup & docs | 30 dk | 8.5 saat |
TOPLAM: ~8.5 saat (yaklaşık 1-2 iş günü)
7. BAŞLANGIÇ NOKTASI
Faz 0'dan başlıyoruz:
-
cluster_info_service'e eksik metodları ekle:get_pods()get_services()check_gadget_health_remote()(HTTP-based)
-
Mevcut test connection fix'ini commit'le
Başlamak için onayınızı bekliyorum.