Services

Every address a Service answers on, one tap from the clipboard — with the cluster’s DNS zones discovered rather than assumed.

Services in Kubo
Services with a type facet and a search that spans name, type, cluster IP, ports and external hostnames.

The Services tab is the kubectl get svc view: namespace-scoped, live over the watch API, with a type facet (ClusterIP, NodePort, LoadBalancer, ExternalName — each with a count) and a free-text search that spans name, namespace, type, cluster IP, port numbers and names, and external hostnames. So “8080”, “https” or part of a load balancer’s hostname all find the row.

The point is the clipboard

On a phone, what you want from a Service is almost always an address you can paste somewhere. So Kubo derives every address a Service answers on:

  • cluster DNS — name.namespace.svc.<domain>, and the short forms;
  • the cluster IP;
  • the node port;
  • any LoadBalancer ingress, external IP, or ExternalName target.

Each is offered as one entry per (domain × address × port), and each is individually copyable. Where a port looks like a web port, a copyable http(s)://… URL is offered too — the scheme is guessed from appProtocol first, then the port’s name, then its number.

Tapping a row copies its primary address in one tap (the external one when there is one, otherwise cluster DNS). The row menu copies the short hostname, the fully-qualified DNS name, host:port or the URL, and opens the Service’s YAML. Tapping the row’s body opens a sheet listing every address separately.

Two honest edge cases:

  • a NodePort has no node IP in the Service object, so Kubo copies just the port and says “on any node IP” rather than inventing an address;
  • a headless service (clusterIP: None) drops the cluster-IP entry, because there isn’t one.

DNS zones are discovered, not assumed

cluster.local is a convention, not a guarantee: a cluster can serve a different zone entirely, and operators often alias a second one. So Kubo reads the CoreDNS ConfigMap in kube-system and parses the Corefile for the kubernetes plugin’s zones (dropping reverse .arpa zones), plus any domain a rewrite name rule aliases onto them — suffix, regex and exact forms, inline and block. Known ConfigMap names are tried first (coredns, AKS’ coredns-custom, RKE2’s, kube-dns), then kube-system is scanned for whatever actually holds a Corefile.

Reading ConfigMaps is an optional permission, so this is detection-gated: any failure falls back to cluster.local.

And because a silent fallback is indistinguishable from a cluster that genuinely serves cluster.local, discovery keeps a trail — every candidate probed, with its outcome (found / not found / forbidden / failed) and error. A banner under the facet chips names the zones in use, flags them when they are assumed rather than discovered, and opens the full trail. Each discovered zone gets its own copyable hostname: the primary one labelled “Cluster DNS”, the rest “Cluster DNS alias”.

Discovery runs once per screen, not per row, so scrolling cannot re-run it.

Events involving a Service deep-link here, so a FailedToUpdateEndpoint warning in the events feed lands on the Service it is about.

Back to Kubernetes.