Skip to content

How do I expose the Kubernetes Services that are running on my Amazon EKS cluster?

6 minute read
52

I want to expose the Kubernetes Services that are running on my Amazon Elastic Kubernetes Service (Amazon EKS) cluster.

Resolution

To expose the Kubernetes Services that are running on your Amazon EKS cluster, first create a sample application. Then, apply the ClusterIP, NodePort, or LoadBalancer Kubernetes Service type to your sample application. For more information, see Service type on the Kubernetes website.

Create a sample application

Complete the following steps:

  1. Define and apply a deployment file in Kubernetes. The following example command creates a file named nginx-deployment.yaml, and then creates a ReplicaSet that spins up two nginx pods:

    cat <<EOF > nginx-deployment.yaml
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: nginx-deployment
      labels:
        app: nginx
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx:1.14.2
            ports:
            - containerPort: 80
    EOF
  2. To create the deployment, run the following command:

    kubectl apply -f nginx-deployment.yaml
  3. To verify that your pods are running and have their own internal IP addresses, run the following command:

    kubectl get pods -l 'app=nginx' -o wide | awk {'print $1" " $3 " " $6'} | column -t

    Example output:

    NAME                               STATUS   IP
    nginx-deployment-574b87c764-hcxdg  Running  192.168.20.8
    nginx-deployment-574b87c764-xsn9s  Running  192.168.53.240

Apply the Service type

Decide how you want to expose your application, and then apply the appropriate Service type. For more information about each Service type, see type: ClusterIP, type: NodePort, and type: LoadBalancer on the Kubernetes website.

ClusterIP Service type

Complete the following steps:

  1. Create a file named clusterip.yaml.

  2. Set type to ClusterIP, as shown in the following example:

    cat <<EOF > clusterip.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service-cluster-ip
    spec:
      type: ClusterIP
      selector:
        app: nginx
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    EOF
  3. Use either a declarative or imperative command to create the ClusterIP object in Kubernetes.
    To create the object and apply the clusterip.yaml file, run the following declarative command:

    kubectl create -f clusterip.yaml

    Example output:

    service/nginx-service-cluster-ip created>/code>

    -or-

    To expose a Deployment of the ClusterIP type, run the following imperative command:

    kubectl expose deployment nginx-deployment  --type=ClusterIP  --name=nginx-service-cluster-ip

    Note: The expose command creates a Service but doesn't create a YAML file. However, kubectl translates your imperative command into a declarative Kubernetes Deployment.
    Example output:

    service "nginx-service-cluster-ip" exposed
  4. To get the CLUSTER-IP address, run the following command:

    kubectl get service nginx-service-cluster-ip

    Example output:

    NAME                       TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
    nginx-service-cluster-ip   ClusterIP   10.100.12.153   <none>        80/TCP    23s
  5. To use the CLUSTER-IP address to access the application, run the following command:

    curl -silent 10.100.12.153:80 | grep title

    Note: To access the Service, you must log into a worker node or be within a Pod's container.

  6. To delete the ClusterIP Service, run the following command:

    kubectl delete service nginx-service-cluster-ip

    Example output:

    service "nginx-service-cluster-ip" deleted

NodePort Service type

Complete the following steps:

  1. Create a file named nodeport.yaml.

  2. Set type to NodePort, as shown in the following example:

    cat <<EOF > nodeport.yaml
    apiVersion: v1
    kind: Service
    metadata:  
      name: nginx-service-nodeport
    spec:
      type: NodePort
      selector:
        app: nginx
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    EOF
  3. Use either a declarative or imperative command to create the NodePort object in Kubernetes.
    To create the object and apply the nodeport.yaml file, run the following declarative command:

    kubectl create -f nodeport.yaml

    -or-

    To expose a Deployment of the NodePort type, run the following imperative command:

    kubectl expose deployment nginx-deployment  --type=NodePort  --name=nginx-service-nodeport

    Example output:

    service/nginx-service-nodeport exposed
  4. To get information about nginx-service, run the following command:

    kubectl get service/nginx-service-nodeport

    Example output:

    NAME                     TYPE       CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
    nginx-service-nodeport   NodePort   10.100.106.151   <none>        80:30994/TCP   27s

    Important: NodePort creates a Service IP address that's accessible within the cluster and uses the specified port to expose the service on every node. The output from the preceding command shows that the NodePort Service type is exposed externally on the port of the available worker node's Amazon Elastic Compute Cloud (Amazon EC2) instance. Before you access NodeIP:NodePort from outside the cluster, set the node security groups to allow incoming traffic through the port that's listed in the output.

  5. For nodes that are in a public subnet and reachable from the internet, check the node's public IP address:

    kubectl get nodes -o wide |  awk {'print $1" " $2 " " $7'} | column -t

    Example output:

    NAME                                      STATUS  EXTERNAL-IP
    ip-10-0-3-226.eu-west-1.compute.internal  Ready   1.1.1.1
    ip-10-1-3-107.eu-west-1.compute.internal  Ready   2.2.2.2

    -or-

    For nodes that are in a private subnet and only reachable through a virtual private cloud (VPC), check the node's private IP address:

    kubectl get nodes -o wide |  awk {'print $1" " $2 " " $6'} | column -t

    Example output:

    NAME                                      STATUS  INTERNAL-IP
    ip-10-0-3-226.eu-west-1.compute.internal  Ready   10.0.3.226
    ip-10-1-3-107.eu-west-1.compute.internal  Ready   10.1.3.107
  6. To use Node IP and the NodePort to access the application, run the following command:

    curl -silent <Public/PrivateNodeIP>:30994 | grep title
  7. To delete the NodePort Service, run the following command:

    kubectl delete service nginx-service-nodeport

    Example output:

    service "nginx-service-nodeport" deleted

LoadBalancer service type

Complete the following steps:

  1. Create a file named loadbalancer.yaml.

  2. Set type to LoadBalancer, as shown in the following example:

    cat <<EOF > loadbalancer.yaml
    apiVersion: v1
    kind: Service
    metadata:
      name: nginx-service-loadbalancer
    spec:
      type: LoadBalancer
      selector:
        app: nginx
      ports:
        - protocol: TCP
          port: 80
          targetPort: 80
    EOF
  3. To apply the loadbalancer.yaml file, run the following command:

    kubectl create -f loadbalancer.yaml

    Example output:

    service/nginx-service-loadbalancer created

    -or-

    To expose a Deployment of the LoadBalancer type, run the following command:

    kubectl expose deployment nginx-deployment  --type=LoadBalancer  --name=nginx-service-loadbalancer

    Example output:

    service "nginx-service-loadbalancer" exposed
  4. To get information about nginx-service, run the following command:

    kubectl get service/nginx-service-loadbalancer |  awk {'print $1" " $2 " " $4 " " $5'} | column -t

    Example output:

    NAME                        TYPE          EXTERNAL-IP                        PORT(S)
    nginx-service-loadbalancer  LoadBalancer  *****.eu-west-1.elb.amazonaws.com  80:30039/TCP
  5. To verify that you can externally access the load balancer, run the following command:

    curl -silent *****.eu-west-1.elb.amazonaws.com:80 | grep title
  6. To delete the LoadBalancer Service, run the following command:

    kubectl delete service nginx-service-loadbalancer

    Example output:

    service "nginx-service-loadbalancer" deleted

Note: By default, the LoadBalancer Service type creates a Classic Load Balancer. For optimal supportability and long-term reliability, it's a best practice to use the AWS Load Balancer Controller to provision Network Load Balancers. This AWS maintained solution provides enhanced features, better integration with AWS services, and support.

To create a Network Load Balancer with an instance type target, add the following annotation to the Service manifest:

service.beta.kubernetes.io/aws-load-balancer-type: nlb

-or-

To create a Network Load Balancer with IP targets, deploy the AWS Load Balancer Controller, and then create a load balancer that uses IP targets.

9 Comments

Could you add how to access the exposed endpoint - e.g., how to construct the URL so we can make API queries / hit it from the browser? You give a piece of that - how to get the IP - but it'd really save on cross-referencing for newer folks if you could share that full process of constructing a URL for testing from the information here.

replied 3 years ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

AWS
MODERATOR
replied 3 years ago

This is great but as being said here we are really missing the client side - How to construct the whole URL and access it with CURL or Postman.

replied 2 years ago

Thank you for your comment. We'll review and update the Knowledge Center article as needed.

AWS
EXPERT
replied 2 years ago

Thanks for providing these good examples in this article, very helpful!

AWS
replied a year ago

Thanks for this article! It is good to have YAML templates handy to apply quickly during troubleshooting or first implementation.

AWS
replied a year ago

Thanks for sharing, very helpful

AWS
replied a year ago

Wonderful content! It has been very useful to be more skilled with Kubernetes, networking and listening ports for my pods.

AWS
replied a year ago

In step 2 of creating the NodePort Service type, there appears to be formatting issues in the YAML file. The correct indentation should be:

metadata:
  name: nginx-service-nodeport
replied 9 months ago