Deploy a gRPC-based application on an Amazon EKS cluster and access it with an Application Load Balancer - AWS Prescriptive Guidance

Deploy a gRPC-based application on an Amazon EKS cluster and access it with an Application Load Balancer

Created by Kirankumar Chandrashekar (AWS) and Huy Nguyen (AWS)

Code repository: grpc-traffic-on-alb-to-eks

Environment: PoC or pilot

Technologies: Containers & microservices; Content delivery; Web & mobile apps

Workload: All other workloads

AWS services: Amazon EKS; Elastic Load Balancing (ELB)

Summary

This pattern describes how to host a gRPC-based application on an Amazon Elastic Kubernetes Service (Amazon EKS) cluster and securely access it through an Application Load Balancer.

gRPC is an open-source remote procedure call (RPC) framework that can run in any environment. You can use it for microservice integrations and client-server communications. For more information about gRPC, see the AWS blog post Application Load Balancer support for end-to-end HTTP/2 and gRPC.

This pattern shows you how to host a gRPC-based application that runs on Kubernetes pods on Amazon EKS. The gRPC client connects to an Application Load Balancer through the HTTP/2 protocol with an SSL/TLS encrypted connection. The Application Load Balancer forwards traffic to the gRPC application that runs on Amazon EKS pods. The number of gRPC pods can be automatically scaled based on traffic by using the Kubernetes Horizontal Pod Autoscaler. The Application Load Balancer's target group performs health checks on the Amazon EKS nodes, evaluates if the target is healthy, and forwards traffic only to healthy nodes.

Prerequisites and limitations

Prerequisites 

Architecture

The following diagram shows the architecture implemented by this pattern.

Architecture for gRPC-based application on Amazon EKS

The following diagram shows a workflow where SSL/TLS traffic is received from a gRPC client that offloads to an Application Load Balancer. Traffic is forwarded in plaintext to the gRPC server because it comes from a virtual private cloud (VPC).

Workflow for sending SSL/TLS traffic to a gRPC server

Tools

AWS services

Tools

  • eksctl is a simple CLI tool for creating clusters on Amazon EKS.

  • kubectl is a command line utility for running commands against Kubernetes clusters.

  • AWS Load Balancer Controller helps you manage AWS Elastic Load Balancers for a Kubernetes cluster.

  • gRPCurl is a command line tool that helps you interact with gRPC services.

Code repository

The code for this pattern is available in the GitHub grpc-traffic-on-alb-to-eks repository.

Epics

TaskDescriptionSkills required

Create an Amazon ECR repository.

Sign in to the AWS Management Console, open the Amazon ECR console, and then create an Amazon ECR repository. For more information, see Creating a repository in the Amazon ECR documentation. Make sure that you record the Amazon ECR repository’s URL.

You can also create an Amazon ECR repository with AWS CLI by running the following command:

aws ecr create-repository --repository-name helloworld-grpc
Cloud administrator

Build the Docker image.

  1. Clone the GitHub grpc-traffic-on-alb-to-eks repository.

    git clone https://github.com/aws-samples/grpc-traffic-on-alb-to-eks.git
  2. From the root directory of the repository, make sure that the Dockerfile exists and then run the following command to build the Docker image: 

    docker build -t <amazon_ecr_repository_url>:<Tag> .

    Important: Make sure that you replace <amazon_ecr_repository_url>  with the URL of the Amazon ECR repository that you created earlier.

DevOps engineer

Push the Docker image to Amazon ECR.

  1. Run the following command to log in to the Amazon ECR repository:

    aws ecr get-login-password --region us-east-1 --no-cli-auto-prompt | docker login --username AWS --password-stdin <your_aws_account_id>.dkr.ecr.us-east-1.amazonaws.com
  2. Push the Docker image to the Amazon ECR repository by running the following command:

    docker push <your_aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/helloworld-grpc:1.0

    Important: Make sure that you replace <your_aws_account_id>  with your AWS account ID.

DevOps engineer
TaskDescriptionSkills required

Modify the values in the Kubernetes manifest file.

  1. Modify the grpc-sample.yaml Kubernetes manifest file in the Kubernetes folder of the repository according to your requirements. You must modify the annotations and host name in the ingress resource. For a sample ingress resource, see the Additional information section. For more information about ingress annotations, see Ingress annotations in the Kubernetes documentation.

  2. In the Kubernetes deployment resource, change the deployment resource's image to the uniform resource identifier (URI) for the Amazon ECR repository that you pushed the Docker image to. For a sample deployment resource, see the Additional information section.

DevOps engineer

Deploy the Kubernetes manifest file.

Deploy the grpc-sample.yaml file to the Amazon EKS cluster by running the following kubectl command: 

kubectl apply -f ./kubernetes/grpc-sample.yaml
DevOps engineer
TaskDescriptionSkills required

Record the FQDN for the Application Load Balancer.

  1. Run the following kubectl command to describe the Kubernetes ingress resource that manages the Application Load Balancer:

    kubectl get ingress -n grpcserver

    Sample output is provided in the Additional information section. In the output, the HOSTS field displays the DNS host name that the SSL certificates were created for.

  2. Record the Application Load Balancer’s fully qualified domain name (FQDN) from the Address field of the output. 

  3. Create a DNS record that points to the Application Load Balancer's FQDN. If your DNS provider is Amazon Route 53, you can create an alias record that points to the Application Load Balancer's FQDN. For more information about this option, see Choosing between alias and non-alias records in the Route 53 documentation.

DevOps engineer
TaskDescriptionSkills required

Test the gRPC server.

Use gRPCurl to test the endpoint by running the following command:

grpcurl grpc.example.com:443 list grpc.reflection.v1alpha.ServerReflection helloworld.helloworld

Note: Replace grpc.example.com with your DNS name.

DevOps engineer

Test the gRPC server using a gRPC client.

In the helloworld_client_ssl.py sample gRPC client, replace the host name from grpc.example.com with the host name used for the gRPC server.  

The following code sample shows the response from the gRPC server for the client's request:

python ./app/helloworld_client_ssl.py message: "Hello to gRPC server from Client" message: "Thanks for talking to gRPC server!! Welcome to hello world. Received message is \"Hello to gRPC server from Client\"" received: true

This shows that the client can talk to the server and that the connection is successful.

DevOps engineer
TaskDescriptionSkills required

Remove the DNS record.

Remove the DNS record that points to the Application Load Balancer's FQDN that you created earlier.

Cloud administrator

Remove the load balancer.

On the Amazon EC2 console, choose Load Balancers, and then remove the load balancer that the Kubernetes controller created for your ingress resource.

Cloud administrator

Delete the Amazon EKS cluster.

Delete the Amazon EKS cluster by using eksctl:

eksctl delete cluster -f ./eks.yaml
AWS DevOps

Related resources

Additional information

Sample ingress resource:

--- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/healthcheck-protocol: HTTP alb.ingress.kubernetes.io/ssl-redirect: "443" alb.ingress.kubernetes.io/backend-protocol-version: "GRPC" alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:<AWS-Region>:<AccountId>:certificate/<certificate_ID> alb.ingress.kubernetes.io/healthcheck-protocol: HTTP labels: app: grpcserver environment: dev name: grpcserver namespace: grpcserver spec: ingressClassName: alb rules: - host: grpc.example.com # <----- replace this as per your host name for which the SSL certtficate is available in ACM http: paths: - backend: service: name: grpcserver port: number: 9000 path: / pathType: Prefix

Sample deployment resource:

apiVersion: apps/v1 kind: Deployment metadata: name: grpcserver namespace: grpcserver spec: selector: matchLabels: app: grpcserver replicas: 1 template: metadata: labels: app: grpcserver spec: containers: - name: grpc-demo image: <your_aws_account_id>.dkr.ecr.us-east-1.amazonaws.com/helloworld-grpc:1.0 #<------- Change to the URI that the Docker image is pushed to imagePullPolicy: Always ports: - name: grpc-api containerPort: 9000 env: - name: POD_IP valueFrom: fieldRef: fieldPath: status.podIP restartPolicy: Always

Sample output:

NAME CLASS HOSTS Address PORTS AGE grpcserver <none> <DNS-HostName> <ELB-address> 80 27d