在 Amazon EKS 集群上部署基于 gRPC 的应用程序并使用应用程序负载均衡器访问它 - AWS Prescriptive Guidance

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

在 Amazon EKS 集群上部署基于 gRPC 的应用程序并使用应用程序负载均衡器访问它

由 Kirankumar Chandrashekar (AWS) 和 Huy Nguyen (AWS) 创作

代码存储库:grpc-traffic-on-albto-eks

环境:PoC 或试点

技术:容器和微服务;内容交付;Web 和移动应用程序

工作负载:所有其他工作负载

Amazon Web Services:Amazon EKS;弹性负载均衡(ELB)

Summary

此模式描述如何在 Amazon Elastic Kubernetes Service (Amazon EKS) 集群上托管基于 gRPC 的应用程序,并通过应用程序负载均衡器安全地访问该应用程序。

gRPC 是一个开源远程过程调用 (RPC) 框架,可以在任何环境中运行。您可将其用于微服务集成和客户端-服务器通信。有关 gRPC 的更多信息,请参阅 AWS 博客文章 App lication Load Balancer 对 end-to-end HTTP/2 和 gRPC 的支持

此模式向您展示如何托管在 Amazon EKS 上的 Kubernetes 容器上运行的基于 GRPC 的应用程序。gRPC 客户端通过 HTTP/2 协议通过 SSL/TLS 加密连接连接连接到 Application Load Balancer。应用程序负载均衡器将流量转发至 Amazon EKS 容器组(pod)上运行的 gRPC 应用程序。使用 Kubernetes Horizontal Pod Autoscaler,可以根据流量自动扩缩 gRPC 容器组(pod)的数量。应用程序负载均衡器的目标组对 Amazon EKS 节点执行运行状况检查,评估目标是否正常,并仅将流量转发到运行状况良好的节点。

先决条件和限制

先决条件

架构

下图显示了此模式实现的架构。

Amazon EKS 上基于 GRPC 的应用程序架构

下图显示了一个工作流,其中从 gRPC 客户端接收 SSL/TLS 流量,然后将其卸载到应用程序负载均衡器。由于流量来自虚拟私有云(VPC),因此以明文形式转发到 gRPC 服务器。

向 gRPC 服务器发送 SSL/TLS 流量的工作流程

工具

Amazon Web Services

工具

  • eksctl 是一款用于在 Amazon EKS 上创建集群的简单 CLI 工具。

  • kubectl 是针对 Kubernetes 集群运行命令的命令行实用程序。

  • AWS 负载均衡器控制器帮助管理 Kubernetes 集群的 AWS 弹性负载均衡器。

  • gRPCurl  是命令行工具,可帮助您与 gRPC 服务进行交互。

代码存储库

此模式的代码可在 to-e GitHub grpc-traffic-on-albks 存储库中找到

操作说明

任务描述所需技能

创建 Amazon ECR 存储库。

登录 AWS 管理控制台,打开 A mazon ECR 控制台,然后创建 Amazon ECR 存储库。有关更多信息,请参阅 Amazon ECR 文档中的创建存储库。请务必记录 Amazon ECR 存储库的 URL。

您也可以通过运行以下命令,使用 AWS CLI 创建 Amazon ECR 存储库:

aws ecr create-repository --repository-name helloworld-grpc
云管理员

构建 Docker 映像。

  1. 克隆 GitHub grpc-traffic-on-albto-eks 存储库。

    git clone https://github.com/aws-samples/grpc-traffic-on-alb-to-eks.git
  2. 在存储库的根目录中,确保 Dockerfile 存在,然后运行以下命令来构建 Docker 镜像: 

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

    重要:请务必<amazon_ecr_repository_url>使用之前创建的 Amazon ECR 存储库的 URL 进行替换。

DevOps 工程师

将 Docker 映像推送到 Amazon ECR。

  1. 运行以下命令以登录 Amazon ECR 存储库:

    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. 通过运行以下命令将 Docker 映像推送到 Amazon ECR 存储库。

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

    重要提示:请务必将 <your_aws_account_id> 更换为 Amazon Web Services account ID。

DevOps 工程师
任务描述所需技能

修改 Kubernetes 清单文件值。

  1. 根据您的要求修改存储grpc-sample.yaml库 Kubernetes 文件夹中的 Kubernetes 清单文件。您必须修改入口资源的注释和主机名。有关示例入口资源,请参阅其他信息部分。有关入口注释的更多信息,请参阅 Kubernetes 文档中的入口注释

  2. 在 Kubernetes 部署资源中,将部署资源的 image 更改为:您将 Docker 映像推至的 Amazon ECR 存储库的统一资源标识符 (URI)。有关此部署资源的样本,请参阅其他信息部分。

DevOps 工程师

部署 Kubernetes 清单文件。

通过运行以下kubectl命令将grpc-sample.yaml文件部署到 Amazon EKS 集群: 

kubectl apply -f ./kubernetes/grpc-sample.yaml
DevOps 工程师
任务描述所需技能

应用程序负载均衡器的 FQDN 记录。

  1. 运行以下 kubectl 命令来描述管理应用程序负载均衡器的 Kubernetes 入口资源:

    kubectl get ingress -n grpcserver

    输出示例在 “其他信息” 部分提供。在输出中,HOSTS 字段显示为其创建 SSL 证书的 DNS 主机名。

  2. 在输出Address字段中记录应用程序负载均衡器的完全限定域名 (FQDN)。 

  3. 创建指向应用程序负载均衡器的 FQDN 的 DNS 记录。如果您的 DNS 提供程序是 Amazon Route 53,请创建一条指向应用程序负载均衡器的 FQDN 的别名记录。有关此选项的更多信息,请参阅 Route 53 文档中的在别名和非别名记录之间进行选择

DevOps 工程师
任务描述所需技能

测试 gRPC 服务器。

通过运行以下命令,使用 gRPCurl 测试端点:

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

注意:请将 grpc.example.com 替换为您的 DNS 名称。

DevOps 工程师

使用 gRPC 客户端测试 gRPC 服务器。

helloworld_client_ssl.py示例 gRPC 客户端中,将中的主机名替换为用于 gRPC 服务器的主机名。grpc.example.com 

下列代码示例显示了 gRPC 服务器对客户端请求的响应:

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

这表明客户端可与服务器通信,并且连接成功。

DevOps 工程师
任务描述所需技能

删除 DNS 记录。

删除您之前创建的指向应用程序负载均衡器的 FQDN 的 DNS 记录。

云管理员

移除负载均衡器。

Amazon EC2 控制台上,选择负载均衡器,然后移除 Kubernetes 控制器为您的入口资源创建的负载均衡器。

云管理员

删除 Amazon EKS 集群。

使用以下方法删除 Amazon EKS 集群eksctl

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

相关资源

其他信息

入口资源示例:

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

部署资源示例:

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

示例输出

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