Understanding Different Types of Services in Kubernetes

Tiffany Hsu
6 min readSep 18, 2023

--

Introduction

In this article, we will explore Kubernetes services and their various types using illustrative diagrams. Kubernetes services play a crucial role in facilitating communication between different components within a Kubernetes cluster. By employing visuals, we aim to demystify the concepts of these services, making it easier to comprehend their functionality and choose the appropriate type for specific use cases. Let’s delve into the world of Kubernetes services and enhance our understanding through visual representation.

Service

Let’s begin with an example of a service. This will create a new service named my-service, as indicated in the metadata field. In this field, there is a controller that scans for pods matching the specified selector. You can think of this like a manager assigning a task and setting specific requirements, such as individuals who can design icons and banners. Similarly, in the case of pods, those labeled as my-app will be included as part of the service.

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

Port Definitions

  • Port definitions in pods have names, allowing you to reference these names in the targetPort field. This eliminates the need to remember the actual port number, thereby conserving our brain’s memory capacity. In the targetPort field, instead of using the port number 80, you can utilize the name. This offers greater flexibility, so if you need to modify the port number, you won’t have to alter the service; you can simply update the port number of the pods.
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app.kubernetes.io/name: proxy
spec:
containers:
- name: nginx
image: nginx:stable
ports:
- containerPort: 80

# HERE IS THE NAME
name: http-web-svc

---
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
selector:
app.kubernetes.io/name: proxy
ports:
- name: name-of-service-port
protocol: TCP
port: 80

# HERE IS THE NAME
targetPort: http-web-svc

Service without Selectors

Let’s try an experiment. If there are no selectors specified, let’s use this manifest to create a service. In this case, we won’t add any selectors.

  • pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80
  • serviceNoSelector.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 80
  • kubectl apply -f serviceNoSelector.yaml
  • Great, let’s test the service. This will open up the browser, but oops 😱, since the service doesn’t select any pods, we won’t see what we expected.
minikube service my-service
  • Let’s modify our service.
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
# lets add the selector under the spec, selects the pod labed with app: myapp
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
  • This is a small experiment to observe the behavior when we don’t have selectors. Without selectors, the service can’t choose pods. Now, let’s delve deeper into an alternative method for services to route requests to pods.

Endpointslice

Since this service does not have selectors to match any pods, you can manually add the EndpointSlice object. Ensure that the kubernetes.io/service-name is set to the service name. By using EndpointSlice, you can efficiently manage the endpoints.

  • service.yaml
apiVersion: v1
kind: Service
metadata:
# service name
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
  • endpointslices.yaml
apiVersion: discovery.k8s.io/v1
kind: EndpointSlice
metadata:
name: my-service-1
labels:
# this name should be set to the service name
kubernetes.io/service-name: my-service
addressType: IPv4
ports:
- name: ''
appProtocol: http
protocol: TCP
port: 9376
# Add the endpoints
endpoints:
- addresses:
- "10.4.5.6"
- addresses:
- "10.1.2.3"
  • In this setup, your application Pods within the cluster can access an external database through the Service. The Pods communicate with the Service, and the Service is responsible for routing the requests to the appropriate external resource based on the available Endpoints.

Service Types

Nodeport

By using NodePort, you can access a service with the NodePort type from outside the cluster. This is achieved by sending a request to any of the nodes in the cluster using the specified node port. The node will then forward the request to the appropriate service, which in turn directs the request to the pods associated with that service. Consequently, the service becomes accessible from outside the cluster.

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
# specified the nodeport to be 30007
nodePort: 30007
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

ClusterIP

ClusterIP is an internal IP type, accessible only within the cluster. This type is assigned to a service when you don’t explicitly specify the type in the YAML file. It’s suitable when your application should only be accessed within the cluster, ensuring internal communication. It’s like an internal phone line for services to communicate with each other.

  • service.yaml
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
  • pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: myapp
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 80

Loadbalancer

It is an extension type of the nodeport service. When using a LoadBalancer service type, incoming traffic from the external world is directed to the load balancer's external IP. The load balancer then routes the traffic to the appropriate nodes and their respective ports based on the defined rules, typically using the NodePort allocated for the service on each node. This abstraction adds an extra layer and ensures that traffic is managed and distributed efficiently across the nodes in the cluster. Direct access to a node from the external world is not typical or intended with a LoadBalancer service type.

apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: LoadBalancer
selector:
app: myapp
ports:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30001

Conclusion

Today, we delved into various service types in Kubernetes, each with its distinct purpose and use cases.

Recap

  • ClusterIP: Ensures your service is contained within the internal network, ideal for internal communications or connections to database pods.
  • NodePort: Opens a specified port on the node, making the service accessible from the external world.
  • Load Balancer: Adds an additional layer in front of the NodePort, enhancing the overall service structure and control.

Your support is greatly appreciated and motivates me to keep sharing insights with you. Thanks for reading! 👏 👏 👏

--

--

No responses yet