How to Use a Kubernetes External Service
Kubernetes is an open-source platform designed to automate containerized applications and deploy, scale, and manage those applications. In a containerized architecture, applications are packaged along with their dependencies into containers. Kubernetes enables managing these containers at scale and offers features such as service discovery, resource bin packing, self-healing capabilities, storage orchestration, and more. |
Kubernetes external services play a crucial role when you want your internal services (running in a Kubernetes cluster) to consume or interact with an external (outside the cluster) service or endpoint using a static name.
For instance, you might have an external database hosted by Amazon RDS, and within your application, you want to refer to this database by the name 'mysql,' not the whole URL provided by AWS. Kubernetes external services facilitate such requirements, providing a mechanism to map an external DNS name to a static name within your cluster.
This article will explain Kubernetes external services in depth and discuss strategies for utilizing them effectively in your environments, including five key configuration best practices and a hands-on walkthrough of creating and configuring a Kubernetes external service.
Summary of key Kubernetes external service concepts
The table below summarizes the Kubernetes external service concepts this article will explore in detail.
Concept | Summary |
Understanding Kubernetes external services | Learn the concept and significance of Kubernetes external services.Understand the different types of Kubernetes services and how they compare to external services. |
Deep dive into Kubernetes external services | Gain insights into the functioning of Kubernetes external services, including service discovery and networking.Discover the lifecycle of a Kubernetes external service. |
How to create and configure a Kubernetes external service | Follow a step-by-step guide to create and configure a Kubernetes External Service.Understand the importance of Kubernetes external services traffic management and load balancing.A detailed example showcases how real-life scenarios leverage Kubernetes external services. |
5 best practices for Kubernetes external service configuration | Learn key strategies and guidelines for efficiently configuring Kubernetes external services.Understand practical ways to manage traffic and load balance and tips for maintaining performance and stability. |
Understanding Kubernetes external services
In Kubernetes, a 'service' is a stable way of accessing a group of Pods. Since Pods can frequently change - destroyed and recreated with new IP addresses - Services allow us to treat this group of Pods as a single, constant entity. This way, applications can reliably communicate without worrying about the underlying Pod changes.
There are four primary types of services in Kubernetes: ClusterIP, NodePort, LoadBalancer, and ExternalName.
Service | Summary |
ClusterIP | This is the default service type.Reachable only within the Kubernetes cluster, as it exposes the service on a cluster-internal IP. |
NodePort | The service gets exposed on a static port on each Node’s IP.Accessible outside the cluster by calling [NodeIP]:[NodePort].In creating a NodePort Service, Kubernetes also creates a ClusterIP service, which the NodePort service will route to. |
LoadBalancer | Typically used by cloud providers, the service gets exposed externally using the cloud provider’s load balancer.When you create a LoadBalancer service, Kubernetes also creates a NodePort and ClusterIP Service. |
ExternalName | Instead of using a proxy, the service gets mapped to the contents of the externalName field (e.g., foo.example.com) by returning a CNAME record with its value. |
Comprehensive Kubernetes cost monitoring & optimization
\> Install in 5 mins or less.Get started
What is an external service in Kubernetes?
A Kubernetes external service is a service that maps to an entity outside of a Kubernetes cluster.
It's important to note that while NodePort and LoadBalancer can be used to expose services to external consumers, they are not identical in function to ExternalName. NodePort and LoadBalancer are used to expose internal services to the outside world.
In contrast, ExternalName provides an alias to an external service, making it addressable as if it were part of your internal network. This could be a service in another namespace, a database hosted elsewhere, or a service in a different data center.
Here is an example of an ExternalName service:
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
Let's break that configuration down line by line:
apiVersion: v1:
Specifies the version of the Kubernetes API you're using to create this object. For a service, this is typically v1.kind:
Service: The type of object you're making. In this case, it's a service.metadata:
This section specifies metadata about the Kubernetes object you're creating.name: my-service:
The name of the service you're making. This unique identifier allows you to interact with the service using kubectl.namespace: prod:
The namespace in which you create the service. Namespaces are a way to divide cluster resources between multiple users or teams. If you don't specify a namespace, Kubernetes will use the default namespace.
spec:
This section defines the desired state of the Service, i.e., what you want the Service to look like.type: ExternalName:
The type of service you're creating. As we've discussed, ExternalName is used to create a Service that acts as an alias for an external service.externalName:
my.database.example.com
:
This service's fully qualified domain name (FQDN) acts as an external service alias.
In simple terms, this configuration creates a service named my-service
in the prod namespace, which acts as an alias for an external service at my.database.example.com
. Any Pods in the same namespace that try to access my-service
will be directed to my.database.example.com
.
Practical applications for Kubernetes external services
There are several scenarios where you might need to use an External Service:
Hybrid deployments: Kubernetes external services are beneficial for hybrid deployments where some services run in a Kubernetes cluster while others operate in different environments, such as on-premises servers.
External dependencies: Certain services, such as storage or databases, may permanently reside outside a cluster due to specific requirements or dependencies.
Migration or restructuring: During a phase of migration or restructuring of your Kubernetes cluster, using an external service helps avoid unnecessary downtime and effectively redirects traffic during the transition. For instance, suppose you want to migrate from one RDS database to another. The URL endpoint of the database will change. As a cluster administrator, you can modify the ExternalName service's endpoint value to reflect this change. Applications that connect to "my-service" won't need to configure any changes. The ExternalName service forwards them to the updated endpoint, abstracting any underlying changes. This ability to seamlessly shift traffic to new external resources without requiring application modifications highlights Kubernetes external services' flexibility.
Deep dive into Kubernetes external services
This section provides an in-depth review of Kubernetes external service operations and lifecycle.
Networking and service discovery for Kubernetes external services
Networking and service discovery are central to how Kubernetes external services operate. When you create an ExternalName service, Kubernetes creates a DNS record for the service within its internal DNS system (typically CoreDNS or kube-DNS).
When a Pod in the cluster tries to access the service (using the service's name), the DNS system returns a CNAME record pointing to the external service's domain name.
A logical overview of service discovery for Kubernetes external services.
Here's a more detailed explanation:
The client (Pod) makes a network request to the ExternalName service by its name (for example,
my-service
).The DNS system within the Kubernetes cluster handles this request as the client is trying to access a service. This process is a fundamental part of the DNS resolution within Kubernetes.
The DNS system responds with a CNAME record that points to the domain name of the external service (as defined in the externalName field).
The client receives this CNAME record and then makes another DNS query to resolve this CNAME to the actual IP address of the external service. This resolution usually involves another DNS system outside of the Kubernetes cluster (for example, a public DNS service like Google DNS).
Once the client has the IP address of the external service, it can connect directly to the external service.
Lifecycle of a Kubernetes external service
The lifecycle of an external service begins with its creation. You define a Service of type ExternalName
in a YAML configuration file and apply it to the cluster using kubectl. Once the service is created, Kubernetes generates a DNS record for it in the internal DNS system.
Throughout its lifecycle, the service simply responds to DNS queries with a CNAME record pointing to the external service. No active connections or forwarding are happening within the service. It simply serves as an alias for the external service.
When you delete the service, Kubernetes removes the corresponding DNS record. Any attempts to access the service after deletion result in a DNS resolution error unless a new service or Pod is created with the same name.
How to create and configure a Kubernetes external service
This tutorial will use Amazon Elastic Kubernetes Service (AWS EKS) as the platform for deploying a Kubernetes cluster to demonstrate the use of external services in Kubernetes. However, several other tools can help you create Kubernetes clusters, including Kind, minikube, and K3s, which are excellent choices for local deployment of Kubernetes clusters. Feel free to use any of these tools if you're more comfortable with them.
Note: Running managed Kubernetes Cluster in cloud vendors will incur hourly costs. We will keep these costs as low as possible in this demo by using AWS Spot instances and cleaning the resources once the demo is completed.
To follow this tutorial, you’ll need:
An AWS account
awscli installed and configured with AWS credentials
eksctl for deploying the EKS cluster
K8s clusters handling 10B daily API calls use Kubecost
Step 1: Deploy the AWS EKS cluster
To create an AWS EKS cluster, we will use eksctl tool. To create the EKS resources, create a cluster.yaml
file with the below configuration.
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: k8s-external-services
region: us-east-1
iam:
withOIDC: true
managedNodeGroups:
- name: node-group-1-spot-instances
instanceTypes: ["t3.small", "t3.medium"]
spot: true
desiredCapacity: 2
volumeSize: 8
addons:
- name: vpc-cni
- name: coredns
- name: aws-ebs-csi-driver
- name: kube-proxy
This file defines the configuration for creating an AWS EKS cluster named k8s-external-services
in the us-east-1
region.
The configuration file also includes
A managed node group called
node-group-1-spot-instances
consisting of spot instances is a cost-effective option for running your workloads.The node group uses a mix of
t3.small
andt3.medium
instance types, with a desired capacity of two nodes and a volume size of 8 GB for each node.The addons section lists the necessary components for the cluster, such as the
VPC CNI
plugin,CoreDNS
for service discovery, theAWS EBS CSI
driver for dynamic provisioning of EBS volumes, andKube-proxy
for managing network traffic between pods and services.
To apply the configuration, execute the command:
> eksctl create cluster -f cluster.yaml
This will create an EKS cluster with a node group of three nodes in the us-east-1 region. Once the cluster is ready, you should see an output similar to the one below.
EKS cluster "k8s-external-services" in "us-east-1" region is ready.
Next, we must update the kubeconfig file with newly created cluster access to interact with the cluster. To update the kubeconfig
, execute the command.
> aws eks --region us-east-1 update-kubeconfig --name k8s-external-services
To confirm the cluster access, run the command to get the Pods from the default namespace.
> kubectl get pods
Step 2: Create the Kubernetes external service
Next, let's create an External Service pointing to httpbin.org, a simple HTTP request/response service. It's a valuable tool for testing and debugging as it can simulate various HTTP responses.
Here's an example YAML configuration file for the external service:
apiVersion: v1
kind: Service
metadata:
name: httpbin-service
namespace: default
spec:
type: ExternalName
externalName: httpbin.org
Here's an explanation of the above yaml manifest:
apiVersion: v1
indicates the API version we use to create this object. In this case, v1 is the version of the core Kubernetes API.kind: Service
: This specifies the kind of Kubernetes object we're creating, which is a service in this case.metadata
: This section provides metadata about the object we're creating. It includesname: httpbin-service
: This is the name of our service. It's unique within a namespace.namespace: default
: This is the namespace where our service will be deployed. If not specified, the "default" namespace is used.
spec
: This is where we define the specific characteristics of our object. For a service, we define the type of service and the external name. It includestype: ExternalName
: This specifies the type of service. An ExternalName service is unique because it doesn't have selectors and doesn't define any ports or endpoints. Instead, it serves as an alias for an external service.externalName:
httpbin.org
: This is where we define the fully qualified domain name (FQDN) to which this service will map. Any traffic that tries to reachhttpbin-service
will be directed tohttpbin.org
.
You can apply this configuration using the kubectl command-line tool:
kubectl apply -f httpbin-service.yaml
Step 3: Deploy the Netshoot container
Now, let's deploy a sample application using Netshoot. Netshoot is a Docker and Kubernetes network troubleshooting tool packed with handy networking tools.
Learn how to manage K8s costs via the Kubecost APIs
Here's an example YAML configuration file to deploy a pod running the Netshoot container:
apiVersion: v1
kind: Pod
metadata:
name: netshoot-pod
namespace: default
spec:
containers:
- name: netshoot
image: nicolaka/netshoot
command: [ "/bin/bash", "-c", "--" ]
args: [ "while true; do sleep 30; done;" ]
You can deploy this Pod by running:
kubectl apply -f netshoot-pod.yaml
Step 4: Test the Kubernetes external service
Once you've deployed the netshoot Pod, you can test connectivity to your external service from within your Kubernetes cluster. You can execute curl commands against the httpbin-service from the netshoot-pod.
Let's test the /uuid and /stream/1 APIs. Open a shell to the netshoot container:
kubectl exec -it netshoot-pod -- /bin/bash
Then execute the curl commands:
curl -X GET httpbin-service/uuid -H "accept: application/json"
curl -X GET httpbin-service/stream/1 -H "accept: application/json"
In the curl commands above, notice that we're using the service name (httpbin-service
) instead of httpbin.org
. This demonstrates how our External Service is an alias that our applications can use to access the httpbin.org service.
This hands-on exercise gives you practical experience with Kubernetes External Services and how they allow your Kubernetes applications to communicate with services outside the cluster.
Step 5: Clean up
To delete the resources and cluster, execute the below commands.
> kubectl delete -f netshoot-pod.yaml
> kubectl delete -f httpbin-service.yaml
> eksctl delete cluster -f cluster.yaml
5 best practices for Kubernetes external service configuration
The five best practices below can help streamline and optimize the configuration of Kubernetes external services.
Ensure DNS resolution is fast and reliable
Ensure that the DNS service (outside your Kubernetes cluster) resolves the externalName (e.g., my.database.example.com) to its actual IP address and is reliable and fast. If DNS resolution is slow or unreliable, it will affect the performance of your applications that rely on the external service. Since the external service depends on DNS resolution to route traffic, any issues or delays in DNS resolution can directly impact the performance of your applications.
Understand your traffic
Understanding your traffic patterns can help you tailor your application's interactions and overall architecture with the External Service for optimized performance and reliability. For instance, if you know that your application will make frequent, short-lived connections to an external service, you might design your application to reuse connections where possible or use connection pooling. Additionally, understanding your traffic patterns might influence other decisions outside of Kubernetes, such as how you configure load balancing or failover mechanisms for the external services.
Plan for changes
A Kubernetes external service's endpoint address can change over time, especially if you don't control it. Plan for these changes by making updating the externalName field in your service easy to update. Using configuration management tools or Kubernetes operators can help automate this process.
Prioritize security
Security plays a significant role when dealing with ExternalName services. Because an ExternalName can point to any DNS endpoint, there's a potential security risk if the endpoint is modified to a malicious value.
Malicious modifications can cause application pods to connect to an unwanted endpoint outside the cluster. To mitigate this risk, ensure that the Service object is secure from unnecessary access by non-admin users. Use role-based access control (RBAC) to restrict access to Kubernetes objects and apply strict controls over who can modify service objects.
Effectively manage traffic and load balancing
While Kubernetes external services do not provide load balancing (since they simply return a CNAME record for the external service), you can use other techniques to manage traffic and load balance between multiple external services.
Multiple External Services: If you have multiple instances of an external service (for example, multiple database replicas), you can create an External Service for each instance and use a Kubernetes Ingress to balance traffic between them.
Using a Real Load Balancer: Another approach is to use an actual load balancer (external to the Kubernetes cluster) that balances traffic between the instances of the external service. The External Service would then point to the load balancer's endpoint.
DNS Optimization: Implement caching in CoreDNS or consider using the NodeLocalDNS project to improve DNS performance and thus enhance the overall performance of your services. This approach reduces the DNS lookup times for external services and can significantly speed up access.
Monitoring: Regularly monitor the performance and availability of your External Services and the external services they point to. Use Kubernetes tools like Prometheus and Grafana for effective monitoring.
Testing: Regularly test the connectivity and performance of your External Services. Be prepared to handle scenarios where the external endpoint is slow or unavailable.
Security: Ensure the safety of your communication between the Kubernetes cluster and the external endpoint. If the data is sensitive, consider using network policies, encryption (like TLS), or even a service mesh to enhance security.