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)

Environment: PoC or pilot

Technologies: Containers & microservices; Content delivery; Web hosting; Websites & web apps

Workload: All other workloads

AWS services: Amazon EKS; Elastic Load Balancing

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 Application Load Balancer support for end-to-end HTTP/2 and gRPC on the Amazon Web Services (AWS) Blog.

This patterns shows you how to host a gRPC-based application that runs as Kubernetes pods on Amazon EKS. The gRPC client connects to an Application Load Balancer through the HTTP/2 protocol with a Secure Sockets Layer/Transport Layer Security (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 only forwards traffic to healthy nodes.

Prerequisites and limitations

Prerequisites 

  • Docker, installed and configured on Linux, macOS, or Windows.

  • An active AWS account.

  • AWS Command Line Interface (AWS CLI) version 2, installed and configured on Linux, macOS, or Windows.

  • An existing Amazon EKS cluster with tagged private subnets, public subnets, and configured to host applications. For more information, see Subnet tagging in the Amazon EKS documentation. 

  • kubectl, installed and configured to access resources on your Amazon EKS cluster. For more information, see Installing kubectl in the Amazon EKS documentation. 

  • gRPCurl, installed and configured.

  • AWS Load Balancer Controller, provisioned in the Amazon EKS cluster.

  • An existing Domain Name System (DNS) host name with a valid SSL or SSL/TLS certificate. You can obtain a certificate for your domain by using AWS Certificate Manager (ACM) or uploading an existing certificate to ACM. For more information about these two options, see Requesting a public certificate and Importing certificates into AWS Certificate Manager in the ACM documentation.

Architecture

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).

Tools

  • AWS CLI – AWS Command Line Interface (AWS CLI) is an open-source tool that enables you to interact with AWS services using commands in your command line shell.

  • Elastic Load Balancing – Elastic Load Balancing distributes incoming application or network traffic across multiple targets, such as Amazon Elastic Compute Cloud (Amazon EC2) instances, containers, and IP addresses, in one or more Availability Zones.

  • Amazon ECR – Amazon Elastic Container Registry (Amazon ECR) is a fully managed Docker container registry.

  • Amazon EKS – Amazon Elastic Kubernetes Service (Amazon EKS) is a managed service that you can use to run Kubernetes on AWS without needing to install, operate, and maintain your own Kubernetes control plane or nodes.

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

  • AWS Load Balancer Controller – AWS Load Balancer Controller manages Elastic Load Balancers for a Kubernetes cluster.

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

Epics

Task Description Skills 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 about this, 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.

Download the helloworld_grpc_alb file (attached) and open the directory. From the root of the directory contents, 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> .

DevOps engineer
Push the Docker image to Amazon ECR.

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 0123456789.dkr.ecr.us-east-1.amazonaws.com

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
Task Description Skills required
Modify the values in the Kubernetes manifest file.

Modify the grpc-sample.yaml Kubernetes manifest file in the Kubernetes directory 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.

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
Task Description Skills required
Record the FQDN for the Application Load Balancer.

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

kubectl get ingress -n grpcserver

A 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. Record the Application Load Balancer’s fully qualified domain name (FQDN) from the Address field. 

Create a DNS record pointing 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, see Choosing between alias and non-alias records in the Route 53 documentation.

DevOps engineer
Task Description Skills 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

Related resources

Additional information

Sample ingress resource:

apiVersion: networking.k8s.io/v1beta1 kind: Ingress metadata: annotations: alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}' 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 kubernetes.io/ingress.class: alb alb.ingress.kubernetes.io/subnets: subnet-XXXXXX,subnet-YYYYYY # <----- Replace with the private subnets within the VPC that hosts the Amazon EKS cluster alb.ingress.kubernetes.io/security-groups: sg-ZZZZZZZZ. # <----- Replace with a security group ID from the VPC where the Amazon EKS cluster is deployed. Make sure that this security group is allowed to access the nodes alb.ingress.kubernetes.io/healthcheck-path: / alb.ingress.kubernetes.io/healthcheck-protocol: HTTP alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-west-2:xxxxx:certificate/xxxxxxx #<----- Replace with the ACM certificate ARN for the DNS hostname labels: app: grpcserver environment: dev name: grpcserver namespace: grpcserver spec: rules: - host: grpc.example.com # <----- Replace as required by your host name that the SSL certificate is available for in ACM http: paths: - backend: serviceName: ssl-redirect servicePort: use-annotation path: /* - backend: serviceName: grpcserver servicePort: 9000

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: 00123456789.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

Attachments

attachment.zip