Kubernetes Networking Deep Dive - Services, Ingress, and Gateway API

sre_panchanan

Panchanan Panigrahi

Posted on March 9, 2024

Kubernetes Networking Deep Dive - Services, Ingress, and Gateway API

Understanding Pod basic concepts

Pods are the smallest deployable unit you can create and manage in Kubernetes.

Each Pod encapsulates tightly coupled containers, shared storage, and networking, offering a cohesive unit for managing application lifecycles.


Let's understand how pods Communicate with each other, without Services.

pods Communicate


Pod-to-Pod Communication within the Same Node:

When pods are on the same node, they can communicate directly using the localhost interface. This means they can use the loopback address (127.0.0.1) or the node's actual IP address to talk to each other. It's like how programs on your computer can communicate with each other using localhost.


Pod-to-Pod Communication across Nodes:

Pod-to-Pod communication across nodes in Kubernetes relies on the networking setup of the cluster. Each pod gets assigned an IP address, allowing them to communicate directly over the network. This communication is facilitated through the networking plugin used in the cluster, which handles routing traffic between nodes.


Fundamental Limitations of Pod Networking

While pod networking in Kubernetes offers a convenient and well-defined paradigm for container-to-container communication within a pod, it inherently possesses limitations that hinder scalability and operational efficiency in production deployments.


Let's Understand them in Detail.

1. Ephemeral Pod IP Addresses:

Pods within a Kubernetes cluster are dynamically assigned unique IP addresses. However, these addresses are ephemeral, meaning they are released upon pod termination. This impermanence poses a significant challenge for applications that require consistent connectivity to specific pods. Traditional methods of hardcoding IP addresses into application configurations become untenable, leading to management overhead and potential errors.

2. Service Discovery Challenges:

The dynamic nature of pod IPs necessitates frequent updates to application configurations whenever a pod IP changes. This manual approach to service discovery becomes cumbersome and error-prone, especially in large deployments with frequent scaling. Maintaining consistency across a distributed application landscape is a significant challenge without a robust service discovery mechanism.

3. Absence of Load Balancing:

Pod networking, by design, does not provide inherent load balancing capabilities. When deploying multiple replicas of a pod (e.g., for horizontal scaling), applications lack the knowledge of which specific pod to target for communication. This can lead to uneven traffic distribution and potential performance bottlenecks, hindering application scalability and high availability.

4. Limited External Visibility:

Pods, by default, are only accessible from within the Kubernetes cluster network. Exposing them to external clients, such as web applications, necessitates complex configurations involving manual port forwarding or intricate network address translation (NAT) setups. This approach becomes unwieldy and error-prone as deployments evolve and external access requirements change.


Services: The Bridge to Scalable and Manageable Deployments

Services

Services in Kubernetes act as an abstraction layer that effectively addresses these limitations. They offer a paradigm shift towards a more robust and manageable approach to application deployment.

Stable Endpoints:

Services provide a logical construct – a stable DNS name or a cluster-internal IP address – that remains constant irrespective of underlying pod IP changes. Applications can reliably connect to the service, and Kubernetes ensures that traffic reaches healthy pods behind the service. This eliminates the need for manual configuration changes in applications due to ephemeral pod IPs.

Automated Service Discovery:

Services seamlessly integrate with deployments or replica sets, automatically registering available pods. Kubernetes maintains the service endpoint with the latest information, ensuring applications can always locate healthy instances for service consumption. This eliminates the need for manual service discovery configurations within applications.

Load Balancing for Scalability:

Services can be configured with a load balancer that efficiently distributes incoming traffic across healthy pods in the backend deployment. This ensures optimal resource utilization and high availability by preventing traffic bottlenecks on individual pods.

Simplified External Exposure:

Services offer various mechanisms, such as NodePorts or Ingress controllers, to expose applications running on pods to external clients. This allows applications to seamlessly interact with the outside world without complex configurations, enhancing deployment flexibility and accessibility.


Now we understand, How Important services are, Lets deep dive into Services.

How kube-proxy Binds Services and Resolves IP Addresses:

kube-proxy

The kube-proxy is a critical component in Kubernetes responsible for managing network traffic between different services and pods within a cluster. Its primary role is to facilitate communication between these entities by implementing a set of network policies defined in the Kubernetes cluster.


How kube-proxy Works:

  1. Service Abstraction:

    • Kubernetes Services provide a stable endpoint (IP and port) for a set of pods, abstracting the underlying pod instances.
    • kube-proxy is responsible for translating these service abstractions into actual network connections.
  2. Service Types:

    • kube-proxy supports different service types, including ClusterIP, NodePort, LoadBalancer, and ExternalName.
    • The service type determines how the service is exposed and how traffic is routed.
  3. Service Discovery:

    • kube-proxy watches the Kubernetes API server for changes in services and endpoints.
    • When a new service is created, kube-proxy configures the necessary rules to handle traffic for that service.
  4. Packet Forwarding:

    • For each service, kube-proxy sets up iptables rules (or an alternative mode like IPVS) to forward packets from the service's ClusterIP to the individual pod endpoints.
  5. Load Balancing:

    • In the case of services with multiple pod endpoints (e.g., replicas), kube-proxy implements simple round-robin load balancing by distributing incoming traffic among the available pods.
  6. NodePort Handling:

    • If a service is of type NodePort, kube-proxy ensures that the specified port on each node forwards traffic to the corresponding ClusterIP service.

IP Resolution:

When a pod wants to communicate with another pod or service, it might use the service name or pod IP. IP resolution in Kubernetes involves translating service names to their corresponding IP addresses.

  1. DNS Resolution:

    • Kubernetes provides DNS-based service discovery. Pods can resolve service names to ClusterIPs through the DNS service provided by the cluster.
    • For example, a pod can use the DNS name my-service.namespace.svc.cluster.local to resolve to the ClusterIP of the service.
  2. ClusterIP Mapping:

    • Once the DNS resolution is done, the client pod communicates with the ClusterIP of the target service.
    • kube-proxy ensures that traffic to the ClusterIP is correctly forwarded to one of the available pod endpoints.
  3. Endpoint Changes:

    • If the set of pod endpoints for a service changes (e.g., due to scaling or pod failure), kube-proxy dynamically updates its forwarding rules to reflect these changes.

Exploring Kubernetes Service Types

Kubernetes offers various service types catering to different networking needs. Understanding these types is crucial for effective cluster communication.

1. ClusterIP

  • Visibility: Internal only (within the cluster).
  • Use case: Ideal for services that only need to be accessed by other services inside the cluster.
  • Pros: Simple to set up, secure by default.
  • Cons: Not accessible from outside the cluster.

2. NodePort

  • Visibility: Accessible from outside the cluster via a static port on each node's IP address.
  • Use case: Useful for exposing services to external clients when a cloud provider load balancer isn't available.
  • Pros: Easy to use for basic external access.
  • Cons: Requires manual configuration of firewall rules on each node for security. Not ideal for high traffic due to load balancing happening at the node level.

3. LoadBalancer

  • Visibility: Externally accessible through a cloud provider's load balancer.
  • Use case: The go-to option for exposing services to the public internet with high traffic and scalability requirements.
  • Pros: Provides automatic load balancing and scales efficiently.
  • Cons: Requires cloud provider support and incurs additional costs.

Choosing the Right Service Type:

Selection depends on your application's needs. ClusterIP is perfect for internal communication, while NodePort offers basic external access. LoadBalancers are best for production environments with high traffic.


Lets understand each Service one-by-one In depth.

At first we have to deploy a Nginx deployment. Then we will create 3 different types of services for this deployment.

Nginx Deployment

Deployment YAML



apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80


Enter fullscreen mode Exit fullscreen mode

This YAML file defines a Kubernetes Deployment named nginx-deployment with three replicas. It uses the official Nginx Docker image and exposes port 80.


Now we will create a ClusterIP Type service for this deployment.

Nginx ClusterIP Service

ClusterIP




apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: ClusterIP


Enter fullscreen mode Exit fullscreen mode

This Kubernetes Service configuration establishes a ClusterIP service for the Nginx Deployment.

Let's delve into its key attributes:

  • Name: nginx-service - This uniquely identifies the service within the Kubernetes cluster.

  • Selector: The service employs the label selector app: nginx to pinpoint and route traffic to pods associated with the Nginx application.

  • Ports:

    • Port: 80 - Exposes the service on port 80 within the ClusterIP.
    • TargetPort: 80 - Directs incoming traffic to port 80 on the selected pods.
  • Type: ClusterIP - Ensures the service is only accessible internally within the Kubernetes cluster. It provides a stable internal IP address for secure communication.


Use Case

The nginx-service ClusterIP service acts as a controlled and stable internal entry point for communication with the Nginx Deployment. It allows other components within the Kubernetes cluster to securely interact with the Nginx service without exposing it to external traffic.


Limitations

While the nginx-service ClusterIP service offers robust internal communication capabilities, it comes with certain limitations:

  1. Internal Access Only: The service is limited to internal cluster access, meaning it cannot be directly accessed from outside the cluster.

  2. Single Port Exposure: Only a single port (port 80 in this case) is exposed externally within the ClusterIP. Additional configurations are needed for exposing multiple ports if required.

  3. No Load Balancing: As a ClusterIP service, it does not provide load balancing capabilities. Load balancing must be handled through alternative means if required.


Nginx NodePort Service

NodePort




apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: NodePort


Enter fullscreen mode Exit fullscreen mode

This Kubernetes Service configuration establishes a NodePort service for the Nginx Deployment.

Let's explore its key attributes:

  • Name: nginx-nodeport-service - Uniquely identifies the service within the Kubernetes cluster.

  • Selector: The service uses the label selector app: nginx to pinpoint and route traffic to pods associated with the Nginx application.

  • Ports:

    • Port: 80 - Exposes the service on port 80 within the NodePort.
    • TargetPort: 80 - Directs incoming traffic to port 80 on the selected pods.
  • Type: NodePort - Exposes the service on a static port on each node's IP. This allows external access to the service.


Accessing the Service

To access the Nginx service externally, you can use the NodePort along with any node's IP and the assigned static port. For example, if the assigned NodePort is 32000:



curl <NodeIP>:32000


Enter fullscreen mode Exit fullscreen mode

Limitations

While NodePort services provide external access to services within a Kubernetes cluster, it's essential to consider some limitations:

  1. Port Range: The NodePort range is 30000-32767 by default. Ensure the chosen port does not conflict with other services or applications on the nodes.

  2. Security: Exposing services using NodePort may introduce security concerns as it opens a range of ports on each node. Consider using additional layers of security, such as firewalls or VPNs, for enhanced protection.

  3. NodeIP Dependency: External access relies on the availability and accessibility of the individual node's IP addresses. Changes in the node's IP may impact external access.


Use Case

The nginx-nodeport-service NodePort service facilitates external access to the Nginx Deployment, but careful consideration of the mentioned limitations is crucial to maintaining a secure and reliable deployment.


Nginx LoadBalancer Service

LoadBalancer




apiVersion: v1
kind: Service
metadata:
  name: nginx-loadbalancer-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
      targetPort: 80
  type: LoadBalancer


Enter fullscreen mode Exit fullscreen mode

This Kubernetes Service configuration sets up a LoadBalancer service for the Nginx Deployment.

Let's explore its key components:

  • Name: nginx-loadbalancer-service - Uniquely identifies the service within the Kubernetes cluster.

  • Selector: The service uses the label selector app: nginx to pinpoint and route traffic to pods associated with the Nginx application.

  • Ports:

    • Port: 80 - Exposes the service on port 80 within the LoadBalancer.
    • TargetPort: 80 - Directs incoming traffic to port 80 on the selected pods.
  • Type: LoadBalancer - Configures the service to use a cloud provider's load balancer, making the service externally accessible.


Use Case

The nginx-loadbalancer-service LoadBalancer service acts as the external entry point for accessing the Nginx Deployment. It distributes incoming traffic across the pods running the Nginx application, ensuring high availability and scalability.

This service configuration is ideal for scenarios where the Nginx service needs to be accessed externally, such as hosting a web application or providing public-facing APIs. It leverages the cloud provider's load balancer to efficiently manage and balance incoming requests.


Limitations

While the LoadBalancer service is effective for external access, it comes with some limitations, such as:

  1. Cost: Cloud provider load balancers may incur additional costs.

  2. Provider Dependency: The LoadBalancer type is specific to cloud providers, limiting portability across different environments.

For a more versatile and feature-rich external access solution, consider using Ingress resources, which provide additional capabilities and flexibility in managing external traffic.


Optimizing External Access with Ingress And Nginx-Ingress-Controller in Kubernetes

Ingress


In Kubernetes, Ingress is an API object that manages external access to services, providing HTTP and HTTPS routing based on rules. It simplifies external connectivity and enables path-based routing for applications.

An Ingress Controller in Kubernetes is a component that manages and facilitates the routing of external traffic to services within the cluster based on rules defined by Ingress resources.


Why do we need an ingress in k8s?

In Kubernetes, Ingress is essential for several reasons:

1. Centralized External Access Management

Ingress provides a centralized and declarative approach to managing external access to services within a Kubernetes cluster. This simplifies the configuration process, allowing for consistent and efficient control over how applications are accessed from outside the cluster.

2. Granular HTTP and HTTPS Routing

With Ingress, you can define rules for HTTP and HTTPS traffic routing, offering a granular level of control. This flexibility enables the specification of different paths, domains, and backend services, optimizing how incoming requests are directed within the cluster.

3. Path-Based Routing for Multi-Application Environments

Ingress supports path-based routing, a crucial feature for hosting microservices under a single domain. This ensures that traffic is directed to the appropriate backend service based on specific URL paths, contributing to a well-organized and scalable infrastructure.

4. SSL Termination for Simplified Certificate Management

Ingress can handle SSL termination, simplifying the management of TLS/SSL certificates. By offloading the decryption of HTTPS traffic, it streamlines the configuration process and enhances security without burdening individual services with certificate-related complexities.

5. Load Balancing for Enhanced Availability

Ingress allows for the configuration of load balancing, distributing incoming traffic across multiple backend pods. This enhances availability and performance, ensuring a balanced workload distribution and facilitating efficient resource utilization.

6. URL Rewriting and Redirection for User-Friendly URLs

Ingress supports URL rewriting and redirection, allowing modifications to requested URL paths before reaching the backend services. This feature is valuable for maintaining clean and user-friendly URLs, contributing to an improved user experience.


Let's understand these concepts through a hands-on example.

When managing external access to services within a Kubernetes cluster, the Nginx Ingress Controller plays a pivotal role in providing advanced routing capabilities.

In this example, we'll explore a configuration that efficiently directs incoming traffic based on specified paths using the Nginx Ingress Controller.


1. Ingress Resource Setup



apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: nginx-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - host: devopsexample.com
      http:
        paths:
          - path: /app
            pathType: Prefix
            backend:
              service:
                name: app-service
                port:
                  number: 80
          - path: /api
            pathType: Prefix
            backend:
              service:
                name: api-service
                port:
                  number: 8080


Enter fullscreen mode Exit fullscreen mode

This Ingress resource is configured to handle external traffic on the domain devopsexample.com and efficiently route requests based on specified paths.

2. Annotations for URL Path Rewriting

The inclusion of the annotation nginx.ingress.kubernetes.io/rewrite-target: / ensures proper URL path rewriting for backend services. This optimization guarantees accurate routing and seamless communication with the specified services.

3. Domain Association

The rules section associates the Ingress with the domain devopsexample.com. This step is crucial for directing traffic from the specified domain to the respective backend services.

4. Path-Based Routing

Path: /app

  • Path Type: Prefix
  • Backend Service: app-service on port 80

Requests starting with /app are directed to the app-service, providing a clear and organized approach to accessing the designated service.

Path: /api

  • Path Type: Prefix
  • Backend Service: api-service on port 8080

For requests beginning with /api, the Ingress routes traffic to the api-service, showcasing the flexibility of the Nginx Ingress Controller in managing distinct paths.


This example highlights the effective use of the Nginx Ingress Controller for optimizing external access within a Kubernetes cluster. By leveraging path-based routing and annotations for URL path rewriting, this configuration ensures a seamless and controlled flow of traffic to designated services, enhancing the overall efficiency of your Kubernetes infrastructure.


Limitations of Ingress in Kubernetes

While Ingress in Kubernetes provides a powerful solution for managing external access, it does have certain limitations that users should be aware of:

1. Lack of Standardized API

Ingress lacks a standardized API, leading to variations in implementation across different Kubernetes environments and Ingress controllers. This lack of standardization can result in compatibility challenges and inconsistent behavior.

2. Limited Support for Advanced Load Balancing

Ingress supports basic load balancing features, but it may not fulfill the requirements of complex networking scenarios. Advanced load balancing configurations, such as weighted routing or traffic mirroring, are often beyond the capabilities of standard Ingress resources.

3. Complexity in Handling WebSocket Connections

Handling WebSocket connections can be challenging with Ingress, as it may require additional configurations and workarounds. This complexity can lead to difficulties in managing real-time applications that heavily rely on WebSocket communication.

4. Limited Support for TCP/UDP Protocols

Ingress primarily focuses on HTTP/HTTPS routing, and support for other transport layer protocols such as TCP or UDP is limited. This constraint may impact scenarios where applications require non-HTTP protocols.

5. Namespace Scope

Ingress resources operate within the scope of a single namespace, limiting their ability to manage external access across multiple namespaces effectively. This can be a constraint in larger Kubernetes deployments with a distributed architecture.

6. Lack of Native TLS Termination

While Ingress can handle TLS termination, the process is often implemented by the Ingress controller rather than the Ingress resource itself. This separation can lead to challenges in managing TLS configurations consistently across different controllers.

To overcome these limitations and introduce improvements to the external access management in Kubernetes, the community has been actively working on the Gateway API.


Gateway API: The Next Step

Gateway API


The Gateway API is an emerging project in the Kubernetes ecosystem that aims to address the limitations of Ingress. It provides a standardized and extensible API for managing external access, offering a more comprehensive set of features and enhanced flexibility for modern application networking.

By exploring the capabilities of the Gateway API, Kubernetes users can look forward to overcoming the limitations associated with traditional Ingress resources and achieving a more robust and scalable solution for managing external traffic.


Conclusion

Navigating Kubernetes networking is a journey that involves understanding pod communication, leveraging services for stability, and harnessing Ingress for advanced routing. Acknowledging their strengths and limitations is key to deploying resilient applications.

In my upcoming blog, we'll deep-dive into the Gateway API—an exciting evolution in Kubernetes networking. Stay tuned for an in-depth exploration of its capabilities and how it addresses the limitations we've uncovered.

Thank you for being part of this exploration. Your interest fuels our commitment to delivering valuable insights. Happy reading and stay tuned for more on the Gateway API!

💖 💪 🙅 🚩
sre_panchanan
Panchanan Panigrahi

Posted on March 9, 2024

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related