-
Notifications
You must be signed in to change notification settings - Fork 128
Description
Executive Summary
Propose to deprecate and remove the ManagedProxyServiceResolver CRD in the next major release of cluster-proxy. This API was designed to expose arbitrary services from managed clusters to the hub cluster through the proxy tunnel. However, its complexity far exceeds the value it provides, especially given that simpler alternatives (service-proxy pattern and direct kube-apiserver access) already exist in the codebase.
Key Decision: We will adopt the service-proxy pattern as the recommended approach for service exposure, which provides the same core functionality with significantly reduced complexity.
API Complexity Analysis
Multi-Layer Dependency Chain
The ManagedProxyServiceResolver API requires understanding and correctly configuring a complex dependency chain:
ManagedProxyServiceResolver (cluster-scoped CRD)
↓ references
ManagedClusterSet (v1beta2)
↓ selects via LabelSelector
ManagedCluster (v1)
↓ points to
Kubernetes Service (on managed cluster)
Any misconfiguration at any level in this chain results in silent failure, making troubleshooting extremely difficult.
Indirect Service Naming
Services are not accessed by intuitive names but through SHA256-hashed hostnames:
// Instead of: prometheus.monitoring.cluster1
// Users must use: cluster-proxy-a1b2c3d4e5f6... (max 63 chars)
// Generation logic:
content := sha256.Sum256([]byte(fmt.Sprintf("%s %s %s", cluster, namespace, service)))
hostname := fmt.Sprintf("cluster-proxy-%x", content)[:63]Impact:
- Users cannot guess or memorize service URLs
- Must use client library or manually calculate hashes
- Debugging connection issues requires understanding the hash algorithm
- No human-readable service discovery
Validation Complexity
File: pkg/util/serviceresolver.go:7-23
func IsServiceResolverLegal(mpsr *ManagedProxyServiceResolver) bool {
// Check managed cluster selector type
if mpsr.Spec.ManagedClusterSelector.Type != ManagedClusterSelectorTypeClusterSet {
return false
}
if mpsr.Spec.ManagedClusterSelector.ManagedClusterSet == nil {
return false
}
// Check service selector type
if mpsr.Spec.ServiceSelector.Type != ServiceSelectorTypeServiceRef {
return false
}
if mpsr.Spec.ServiceSelector.ServiceRef == nil {
return false
}
return true
}Problems:
- No admission webhook validation
- Invalid resources are created but silently ignored
- Status controller only reports errors, doesn't prevent creation
- Users discover issues only after deployment
Maintenance Burden
Code Distribution
ManagedProxyServiceResolver touches 23+ files across the codebase:
| Category | Files | Examples |
|---|---|---|
| CRD definitions | 2 | managedproxyserviceresolver_types.go, CRD manifests |
| Generated code | 10+ | clientset, informers, listers, deepcopy |
| Core logic | 5 | agent.go, serviceresolver.go, client.go |
| Controllers | 1 | service_resolver_controller.go |
| Tests | 3 | unit tests, integration tests, e2e tests |
| Documentation | 3 | access-exported-services.md, access-prometheus.md |
| Total | 23+ |
Additional Runtime Components
ServiceResolverReconciler Controller:
// File: pkg/proxyserver/controllers/service_resolver_controller.go
// Watches:
// 1. ManagedProxyServiceResolver changes
// 2. ManagedClusterSet changes (triggers reconciliation)
// Responsibilities:
// - Validate MPSR spec
// - Check if referenced ClusterSet exists
// - Update status conditionsImpact:
- Additional controller running in addon-manager
- Increases memory and CPU usage
- More code to test and maintain
- Version compatibility concerns
Service Proxy Pattern
The service-proxy pattern provides human-readable, intuitive URLs for accessing services on managed clusters:
https://cluster-proxy-addon-user.open-cluster-management-addon.svc:9092/<cluster-name>/api/v1/namespaces/<namespace>/services/<protocol>:<service-name>:<port>/<path>
URL Pattern Breakdown:
https://cluster-proxy-addon-user.open-cluster-management-addon.svc:9092
└─ Hub service endpoint
/cluster1
└─ Managed cluster name (human-readable!)
/api/v1/namespaces/default/services
└─ Standard Kubernetes API path
/http:hello-world:8000
└─ protocol:service-name:port (clear and descriptive)
/proxy-service/index.html
└─ Path to the actual resource
Compare
// Old (MPSR):
proxyHost, _ := clusterproxyclient.GetProxyHost(ctx, cfg, cluster, ns, svc)
url := fmt.Sprintf("http://%s:%d", proxyHost, port) // cryptic hash
// New (Service-Proxy):
url := fmt.Sprintf(
"https://cluster-proxy-addon-user.open-cluster-management-addon.svc:9092/%s/api/v1/namespaces/%s/services/http:%s:%d/proxy-service/",
cluster, ns, svc, port,
) // human-readable!Metadata
Metadata
Assignees
Labels
Type
Projects
Status