Documentation
¶
Overview ¶
Package k8s implements the Registry interface using the Kubernetes API server as the backend. It discovers service endpoints by listing pods with the aether.io/managed=true label and derives service names from each pod's ServiceAccount. Node topology labels provide region and zone locality information.
Index ¶
- type Config
- type KubernetesRegistry
- func (r *KubernetesRegistry) Close() error
- func (r *KubernetesRegistry) Initialize(_ context.Context) error
- func (r *KubernetesRegistry) ListAllEndpoints(ctx context.Context, protocol registryv1.Service_Protocol) (map[string][]*registryv1.ServiceEndpoint, error)
- func (r *KubernetesRegistry) ListEndpoints(ctx context.Context, service string, protocol registryv1.Service_Protocol) ([]*registryv1.ServiceEndpoint, error)
- func (r *KubernetesRegistry) RegisterEndpoint(_ context.Context, _ string, _ registryv1.Service_Protocol, ...) error
- func (r *KubernetesRegistry) UnregisterEndpoint(_ context.Context, _ string, _ string) error
- func (r *KubernetesRegistry) UnregisterEndpoints(_ context.Context, _ string, _ []string) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Config ¶
type Config struct {
// ClusterName is the name of the cluster, used to populate ServiceEndpoint.ClusterName.
ClusterName string
}
Config holds the configuration for the Kubernetes registry backend.
type KubernetesRegistry ¶
type KubernetesRegistry struct {
// contains filtered or unexported fields
}
KubernetesRegistry is a Registry implementation backed by the Kubernetes API server. It reads pods labeled with aether.io/managed=true and converts them to ServiceEndpoints. Write operations (Register/Unregister) are no-ops since the API server is the source of truth.
func NewKubernetesRegistry ¶
NewKubernetesRegistry creates a new Kubernetes API server backed Registry. The reader should be a direct API reader (e.g., manager.GetAPIReader()) to avoid cache synchronization issues during startup.
func (*KubernetesRegistry) Close ¶
func (r *KubernetesRegistry) Close() error
Close is a no-op for the Kubernetes registry.
func (*KubernetesRegistry) Initialize ¶
func (r *KubernetesRegistry) Initialize(_ context.Context) error
Initialize is a no-op for the Kubernetes registry. The API server connection is managed by the controller-runtime manager.
func (*KubernetesRegistry) ListAllEndpoints ¶
func (r *KubernetesRegistry) ListAllEndpoints(ctx context.Context, protocol registryv1.Service_Protocol) (map[string][]*registryv1.ServiceEndpoint, error)
ListAllEndpoints returns all endpoints for all services, grouped by service name (ServiceAccount). It lists all managed pods, resolves node localities, and converts each pod to a ServiceEndpoint.
Pods are filtered by the protocol each declares in endpoint.aether.io/protocol, exactly as in ListEndpoints — see there for why this backend used to return an empty map for TCP and why it no longer has to (#878). A service with no pod serving the requested protocol is absent from the result rather than present and empty, so the agent's cluster passes see only the services they should build.
func (*KubernetesRegistry) ListEndpoints ¶
func (r *KubernetesRegistry) ListEndpoints(ctx context.Context, service string, protocol registryv1.Service_Protocol) ([]*registryv1.ServiceEndpoint, error)
ListEndpoints returns all endpoints for a service by listing managed pods whose ServiceAccount matches the given service name. Node topology labels are used for locality information.
Endpoints are filtered by the protocol each POD declares in endpoint.aether.io/protocol, so a query for P returns exactly the pods serving P (#878).
This backend used to return nothing at all for a TCP query. That was a workaround, not a property of Kubernetes: podToEndpoint ignored the protocol annotation, so every managed pod looked like an HTTP endpoint, and answering a TCP query with that same set made every mesh service collapse to a TCP-only entry — the agent's LoadClustersFromRegistry builds a service's HTTP cluster (with its outbound and cap_http vhosts) from the HTTP listing, then OVERWRITES the same map key with a vhost-less tcp:true entry from the TCP listing. The CDS cluster and GAMMA vhost vanished and captured requests 503'd with no_healthy_upstream.
Reading the annotation removes the need for the workaround: a pod declaring "tcp" appears only in the TCP listing and a pod declaring "http" only in the HTTP one, so the two listings are disjoint and the agent's second pass has nothing to clobber. The "a service is HTTP or TCP, never both" invariant still holds, because every pod behind one ServiceAccount carries the same annotation.
Filtering runs in BOTH directions on purpose. Returning HTTP-declaring pods under TCP is the bug above; returning TCP-declaring pods under HTTP is the same bug mirrored, and would put a raw-TCP pod behind an h2 cluster.
func (*KubernetesRegistry) RegisterEndpoint ¶
func (r *KubernetesRegistry) RegisterEndpoint(_ context.Context, _ string, _ registryv1.Service_Protocol, _ *registryv1.ServiceEndpoint) error
RegisterEndpoint is a no-op. The Kubernetes API server is the source of truth for pod endpoints.
func (*KubernetesRegistry) UnregisterEndpoint ¶
UnregisterEndpoint is a no-op. The Kubernetes API server is the source of truth for pod endpoints.
func (*KubernetesRegistry) UnregisterEndpoints ¶
UnregisterEndpoints is a no-op. The Kubernetes API server is the source of truth for pod endpoints.