Kubernetes Services

Learn about Service in Kubernetes, specifying pods, using services for external workloads, cluster federation, kubectl, and more.

December 10, 2020

In this page, you’ll find everything you need to know about Services in Kubernetes:

What is a Service in Kubernetes?

For Kubernetes, a service is an abstraction that represents a set of logical pods where an application or component is running, as well as embedding an access policy to those pods. Actual pods are ephemeral, Kubernetes guarantees the availability of pods and replicas specified but not the liveliness of each individual pod. This means that other pods that need to communicate with this application or component cannot rely on the underlying individual pod’s IP addresses.

A service gets allocated a virtual IP address as well (called a clusterIP in Kubernetes), and lives until explicitly destroyed. Requests to the service get redirected to the appropriate pods, thus the service serves as a stable endpoint used for inter-component or application communication. For Kubernetes-native applications, requests can also be made via an API in Kubernetes’ apiserver which automatically exposes and maintains the actual pods endpoints at any moment.

For further reading, see Kubernetes Documentation: Services ›

Service Types Comparison: ClusterIP vs NodePort vs LoadBalancer vs Ingress

NodePorts, LoadBalancers, and Ingress are different ways to get external traffic into a Kubernetes cluster. Below we explain the differences between these types of services.

ClusterIP

A ClusterIP service is the default type of service in Kubernetes. It creates a service inside the Kubernetes cluster, which can be accessed by other applications in the cluster, without allowing external access.

A ClusterIP exposes the following:

spec.clusterIp:spec.ports[*].port

NodePort

A NodePort service opens a specific port on all the Nodes in the cluster, and any traffic sent to that port is forwarded to the service. The service cannot be accessed from the cluster IP. 

A NodePort exposes the following:

<NodeIP>:spec.ports[*].nodePort
spec.clusterIp:spec.ports[*].port

LoadBalancer

A LoadBalancer is a standard way to expose a Kubernetes service externally so it can be accessed over the internet. If you are using Google Kubernetes Engine (GKE), this creates a Network Load Balancer with one IP address, which external users can access and are then forwarded to the relevant node in your Kubernetes cluster. A LoadBalancer can also be accessed in the same way as a ClusterIP or NodePort

A LoadBalancer exposes the following:

spec.loadBalancerIp:spec.ports[*].port
<NodeIP>:spec.ports[*].nodePort
spec.clusterIp:spec.ports[*].port

Ingress

Ingress is actually not a type of service. It sits in front of multiple services and performs smart routing between them, providing access to your cluster. There are several types of ingress controllers that have different routing capabilities. In GKE, the ingress controller creates an HTTP Load Balancer, which can route traffic to services in the Kubernetes cluster based on path or subdomain.

Specifying Pods in a Service

A service in Kubernetes can be created via an API request by passing in a service definition such as:

kind: Service
apiVersion: v1
metadata:
  name: my-service
spec:
  selector:
    app: MyApp
  ports:
    - protocol: TCP
      port: 80
      targetPort: 9376

In this example the new service is named my-service and will target TCP port 9376 on any pod with the metadata label "app=MyApp" . Kubernetes constantly evaluates the service’s label selector to determine at any given moment which pods are included in the service. This means that a new service can include existing pods that already match the label selector.

To facilitate port changes in the pods/applications, Kubernetes supports strings for targetPorts, so each pod in the service can expose a different port, as long as there’s a mapping to a commonly named port. This allows, for example, to change the port number that pods expose in the next version of your backend software, without breaking clients.

For further reading, see Kubernetes Documentation: Defining a Service ›

Using Services for External Workloads

A service can apply to an external workload as well, allowing to use the same abstraction to connect to a backend or database running outside Kubernetes, for example. Pods can then connect to this service and without knowing about specific endpoints for workloads outside of Kubernetes.

In order to do so the service should be defined as in previous section but without the label selector. After the service is created, the endpoints for the external workload need to be specified. For example:

kind: Endpoints
apiVersion: v1
metadata:
 name: my-service
subsets:
 - addresses:
- ip: 62.82.24.195
 ports:
 - port: 9376

All incoming traffic to my-service will get routed straight through to endpoint 62.82.24.195:9376.

For further reading, see Kubernetes Documentation: Services without selectors ›

Service Types

The default and simplest service type is ClusterIP . It exposes the service’s ClusterIP address internally to the Kubernetes cluster. Other types allow different access policies to the service and include:

  • NodePort – exposes the service on the specified port number, on all nodes in the Kubernetes cluster. Meaning that an incoming request to a node’s IP on the specified port will get routed to the service’s ClusterIP .
  • LoadBalancer – service is exposed like in NodePort but creates a load balancer in the cloud where Kubernetes is running (if supported by the cloud provider) that receives external requests to the service. It then distributes them among the cluster nodes using NodePort. To specify this type add this line to the spec:
type: LoadBalancer
  • ExternalName – returns an alias to an external component residing outside the Kubernetes cluster. An incoming request for the service gets routed by Kubernetes DNS to the external domain specified. For example, to redirect traffic sent to my-service to my.database.example.com :
kind: Service
apiVersion: v1
metadata:
  name: my-service
  namespace: default
spec:
  type: ExternalName
  externalName: my.database.example.com

For further reading, see Kubernetes Documentation: Publishing services – service types ›

Service Discovery

Service discovery in Kubernetes can be achieved via the cluster DNS (recommended) or via environment variables on the nodes.

The DNS server watches the Kubernetes API for new services and creates a set of DNS records for each. Pods can then access services via standard DNS name resolution. If namespaces are being used in the cluster, then pods outside need to qualify the namespace of the service, for example by calling my-service.my-namespace instead of just my-service .

Environment variables are less reliable as a pod might fail to reach a service that was created after the pod. Kubernetes exports a set of environment variables for each service currently active in the Kubernetes cluster at pod creation time. These variables are exported on the node where the pod gets created, so they become visible to the pod. For example, these variables (and more) would get exported for each of the active services payments and orders:

PAYMENTS_SERVICE_HOST=10.0.0.11
PAYMENTS_SERVICE_PORT=6379
ORDERS_SERVICE_HOST=10.0.171.239
ORDERS_SERVICE_PORT=6379

But if the orders service did not exist yet at pod creation time, then orders would not be visible to the pod through environment variables.

For further reading, see Kubernetes Documentation: Discovering services ›

Multi-Cluster Services with Cluster Federation

Kubernetes Cluster Federation allows a (federated) service to run on multiple Kubernetes clusters simultaneously. The clusters can be spread across different cloud providers, availability zones and even private clouds, as long as the cluster’s API endpoint and credentials are registered with the Federation API server.

A new federated service can be created by calling the Federation API in the same manner as a cluster-specific kube-apiserver would be called for a (non-federated) service (as described in this article up to now). Federation means that the service will be sharded across all the Kubernetes clusters that are part of the federation.

A pod can access a federated service in a similar fashion to a regular service, by adding the federation name. For example calling my-service.my-namespace.my-federation gets automatically resolved by Kubernetes DNS server to the (geographically) nearest cluster where the service is running (under normal circumstances this would be service shard in the same cluster where the pod resides).

The health of the service in each cluster is automatically monitored and a set of DNS records is kept up-to-date accordingly. Such records are set up in an hierarchical way. For example, a request sent to the top-level record:

my-service.mynamespace.my-federation.svc.example.com

could get forwarded to any (healthy) service endpoint on any of the federated clusters (on any zone, region or provider). However, a request sent to

my-service.my-namespace.my-federation.svc.europe-west1-d.example.com

will get forwarded to an endpoint in a cluster inside availability zone europe-west1-d.

Should there be no healthy service shard running in that zone, the request will get forwarded to a cluster on another availability zone in the europe-west1 region, Should that still fail to reach a healthy service, then the request would get forwarded to the top-level:

my-service.mynamespace.my-federation.svc.example.com

and possibly get handled by a service shard in a different region or even a different cloud provider.

Federation provides high availability of services, availability zone fault tolerance and built-in service discovery across multiple zones, regions, providers and on-premise clusters.

For further reading, see Kubernetes Documentation: Cross-cluster Service Discovery using Federated Services ›

Common operations with kubectl

The kubectl command line makes it easier to run some common operations with Kubernetes services:

  • Create a service – It’s possible to specify that all deployed pods in a given deployment are part of a new service. For example this command will create service my-nginx which targets TCP port 80 on any pod with the run: my-nginx metadata label:
$ kubectl expose deployment/my-nginx
  • Describe a service – This is useful to check that the service was created as expected or to find out its ClusterIP or the endpoints of the pods currently part of the service. To describe service my-nginx :
$ kubectl describe svc my-nginx
  • List all services – For a full list of services running in the cluster, run kubectl get services
  • Check if Kubernetes DNS service is running : The DNS service must be up and running for service discovery via name resolution to work. To check if it’s running in a cluster run:
$ kubectl get services kube-dns --namespace=kube-system
  • Remove a service –  kubectl delete is the command for deleting Kubernetes resources. For example, to remove service my-nginx run:
$ kubectl delete svc my-nginx

For further reading, see Kubernetes Documentation: kubectl ›

Summary

Services are an abstraction that allows the underlying pods to change (some get deleted, some get created) without the service clients needing to keep track of which pods are available at any point. This is done via a clusterIP address for the service. To expose the service to the outside world, the service must be defined as type NodePort or LoadBalancer . It’s also possible to redirect service requests to an external resource by means of an ExternalName type of service. This provides support for interoperability and migration scenarios. A federated service is essentially a regular service replicated across multiple Kubernetes clusters, which might live in different availability zones, cloud providers or even on-premise, supporting high availability and availability zone fault tolerance.  

Top Kubernetes Services Tutorials from the Community

Using a Service to Expose Your App

Tutorial by: Kubernetes

Length: Medium

Can help you learn: Pod labels, how to maintain and update running pods using deployments, creating and managing services, process and application health checking.

Tutorial Steps:

  • Overview of Kubernetes Services
  • Understand how labels and LabelSelector objects relate to a Service
  • Explore an application outside a Kubernetes cluster using a Service

Debug Services

Tutorial by: Kubernetes

Length: Medium

Can help you learn: Checking if a service is running, checking if a service is discoverable via DNS, checking if the pods in a service are working and have valid endpoints, checking if kube-proxy is working

Tutorial Steps:

  • Setup
  • Does the service exist?
  • Does the service work by DNS and IP?
  • Are the pods working?
  • Is the kube-proxy working?

Using a Service to Expose Your App

Tutorial by: Kubernetes

Length: Long

Can help you learn: About Services in Kubernetes, understand how labels and LabelSelector objects relate to a service, expose an application outside a Kubernetes cluster using a Service

Tutorial steps:

  • Overview of Kubernetes Services
  • Create a new service
  • Using labels
  • Deleting a service

Kubernetes Cluster Federation (The Hard Way)

Tutorial by: Kelsey Hightower

Length: Long

Can help you learn: Setting up a Kubernetes cluster federation across multiple Google Cloud Platform regions, understand each task required to bootstrap a Kubernetes cluster federation, how to run federated services and secrets

Tutorial steps:

  • Bootstrapping tasks
  • Provision federated control plane
  • Adding clusters to the federation
  • Running federated workloads
  • Delete federated cluster

Securing the Service

Tutorial by: Kubernetes

Length: Medium

Can help you learn: How to secure a service before exposing it to the outside world

Tutorial steps:

  • Set up public private key pair
  • Create a Kubernetes secret with a YAML file
  • Modify a service to use the certificate in the secret

Top Docker Images Videos

Services Overview
This video is a brief overview of the service abstraction, why it’s needed and how to specify pods in a service.
Understanding Service Discovery
Teaches you how to use services to securely expose pods to internal and external consumers. Covers service discovery through environment variables and through DNS. Describes the differences between ClusterIP, NodePort, and LoadBalancer service types.
Deploying Self Healing Services With Kubernetes
Shows you how Kubernetes automatically redistributes systems, including some real world examples. Best practices for deploying self healing services with Kubernetes, including readiness probes, liveness probes, and affinity configuration.
Kubernetes Federation
Discusses the kind of problems Kubernetes Federation helps solve and how.
Cluster Integration: Services – Getting in and out of the cluster
Gives you an understanding of the networking differences between pods, nodes (VMs), and services. How service discovery through DNS works.