简体   繁体   English

使用 Nginx-Ingress-Controller 在 AWS 上的 EKS 中使用 gRPC

[英]gRPC in EKS on AWS with Nginx-Ingress-Controller

I have a gRPC server set up in AWS EKS, and use Nginx-Ingress-Controller to perform load balancing.我在 AWS EKS 中设置了 gRPC 服务器,并使用 Nginx-Ingress-Controller 执行负载平衡。 I try to terminate TLS at NLB, by setting the gRPC server ingress to like我尝试通过将 gRPC 服务器入口设置为 like 来终止 NLB 的 TLS

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
  name: my-grpc
  namespace: myspace
spec:
  rules:
    - host: my.test.com
      http:
        paths:
          - path: /
            backend:
              serviceName: grpc-server
              servicePort: 8080

Also, I use Amazon Certificate Manager to manage the TLS for NLB, so I have to change the Helm Chart of Nginx-Ingress-Controller Value.yaml the following fields另外,我使用 Amazon Certificate Manager 来管理 NLB 的 TLS,所以我必须更改 Nginx-Ingress-Controller Value.yaml 的 Helm Chart 以下字段

controller:
  service:
    enabled: true
    annotations: 
      service.beta.kubernetes.io/aws-load-balancer-ssl-cert: arn:aws:acm:xxxxxxxxxxx
      service.beta.kubernetes.io/aws-load-balancer-backend-protocol: http
      service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443,8443"
      service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "3600"
      service.beta.kubernetes.io/aws-load-balancer-type: nlb
      service.beta.kubernetes.io/aws-load-balancer-internal: "true"

    targetPorts:
      http: http
      https: http

The problem is, I could not successfully call through 443 port and make the client connect to the gRPC server.问题是,我无法通过 443 端口成功调用并使客户端连接到 gRPC 服务器。

The problem happens between NLB and Nginx, but what and why is unknown.问题发生在 NLB 和 Nginx 之间,但原因和原因尚不清楚。 Any kind of help will be appreciated.任何形式的帮助将不胜感激。

Note: I am aware of the example ingress-nginx has TLS field, but what I should put here if I am using ACM.注意:我知道示例ingress-nginx有 TLS 字段,但是如果我使用 ACM,我应该把它放在这里。

I finally got something working through AWS + NLB + EKS.我终于通过 AWS + NLB + EKS 得到了一些东西。 I started with this basic grpc app我从这个基本的 grpc 应用开始

Swap out ever instance of 'fortune-teller.stack.build' with your URL (eg example.com)用您的 URL(例如 example.com)交换“fortune-teller.stack.build”的任何实例

In the ingress, I had to change tls -> secret Name to the tls-secret that I created earlierusing this guide在入口中,我必须将tls -> secret Name 更改为我之前使用本指南创建的 tls-secret

kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: "nginx"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    nginx.ingress.kubernetes.io/backend-protocol: "GRPC"
  name: fortune-ingress
  namespace: default
spec:
  rules:
  - host: example.com
    http:
      paths:
      - backend:
          serviceName: fortune-teller-service
          servicePort: grpc
  tls:
  - secretName: tls-secret
    hosts:
      - example.com

In cert.yaml, change在 cert.yaml 中,更改

  1. spec -> Domain to my URL (example.com)规格 -> 域到我的 URL (example.com)

In svc.yaml, added annotations and "type: LoadBalancer"在 svc.yaml 中,添加注解和“类型:LoadBalancer”

apiVersion: v1
kind: Service
metadata:
  name: fortune-teller-service
  namespace: default
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-internal: "false"
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "arn:aws:acm:<REGION>:<MY ACCOUNT>:certificate/<CERT ID>"
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "443"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
spec:
  type: LoadBalancer
  selector:
    k8s-app: fortune-teller-app
  ports:
  - port: 50051
    targetPort: 50051
    name: grpc

Once all of that is deployed via the Readme, find the NLB in the AWS console.通过自述文件部署所有内容后,在 AWS 控制台中找到 NLB。

  1. Listeners tab -> select the listener (50051) and click 'edit'侦听器选项卡 - > select 侦听器 (50051) 并单击“编辑”
  2. Change protocol to TLS and I changed the port to 443将协议更改为 TLS,我将端口更改为 443
  3. Under ALPN Policy, Select "HTTP2Only"在 ALPN 策略下,Select "HTTP2Only"
  4. Keep the same target group under "Default Actions -> forward to"在“默认操作 -> 转发到”下保持相同的目标组
  5. Select a policy version ( I chose ELBSecurityPolicy2016-08 but will be upgrading this) and your cert from ACM that is tied to your URL Select 一个策略版本(我选择了 ELBSecurityPolicy2016-08 但将升级它)和您来自 ACM 的证书,它与您的 URL
  6. Click "Update"点击“更新”
  7. Point your DNS name to your NLB将您的 DNS 名称指向您的 NLB

Now wait...as the listener update seems to take a few minutes.现在等待...因为侦听器更新似乎需要几分钟。

grpcurl example.com:443 build.stack.fortune.FortuneTeller/Predict

I was also able to get my app working successfully by swapping out image, port and of course the names.通过交换图像、端口,当然还有名称,我还能够让我的应用程序成功运行。

Mistakes I was making that made it not work for me:我犯的错误使它对我不起作用:

  • Not having a TLS secret in the ingress入口中没有 TLS 密钥
  • Trusting the AWS docs when they say that your Target group has to be a "TLS Target Group".当 AWS 文档说您的目标组必须是“TLS 目标组”时,请相信他们。 If you follow this example, you never swap the TG.如果您遵循此示例,则永远不会交换 TG。 The TG stays as a TCP TG and still works. TG 保持为 TCP TG 并且仍然有效。

Thank CrookedSmile for his answer, but it turns out my problem has a root cause in my Nginx-Ingress-Controller Setup and I finally solve it in this way:感谢 CrookedSmile 的回答,但事实证明我的问题在我的 Nginx-Ingress-Controller 设置中有根本原因,我最终以这种方式解决了它:

I mistakenly think to terminate TLS at NLB and Terminate TLS at Nginx is the same thing when I use Nginx-Ingress-Controller.当我使用 Nginx-Ingress-Controller 时,我错误地认为在 NLB 终止 TLS 和在 Nginx 终止 TLS 是一回事。 But it is not.但事实并非如此。

In my situation, I do not need to terminate TLS at NLB, I need to terminate it at Nginx.在我的情况下,我不需要在 NLB 终止 TLS,我需要在 Nginx 终止它。

So I do the following 2 things:所以我做了以下两件事:

  1. I revert what I do following this section AWS L7 ELB SSL Termination .我恢复了我在本节AWS L7 ELB SSL Termination之后所做的事情。

  2. Nginx is configured by my application Ingress file. Nginx 由我的应用程序入口文件配置。 So I must set the TLS fields of the gRPC server ingress like ingress.yaml example here .所以我必须在这里设置 gRPC 服务器入口的 TLS 字段,例如ingress.yaml 示例

Then TLS is successfully terminated at Nginx and I could call my gRPC server behind NLB with Nginx-Ingress-Controller in between.然后 TLS 在 Nginx 成功终止,我可以在 NLB 后面调用我的 gRPC 服务器,并在两者之间使用 Nginx-Ingress-Controller。

Additional Note: Currently, Nginx-Ingress-Controller does not support ACM yet (July 1 2020), so you have to manage each certificate on your own.附加说明:目前,Nginx-Ingress-Controller 尚不支持 ACM(2020 年 7 月 1 日),因此您必须自己管理每个证书。

@CrookedSmile - When you deploy a service with type as LoadBalancer, it creates a Network Loadbalancer in your AWS account. @CrookedSmile - 当您部署类型为 LoadBalancer 的服务时,它会在您的 AWS 账户中创建一个网络负载均衡器。 Now, when you create an Nginx Ingress controller, that's another Loadbalancer that is being created under the hood.现在,当您创建 Nginx 入口 controller 时,这是另一个正在后台创建的负载均衡器。 As per your instructions, you are exposing the service over Loadbalancer - created as a part of the service type.根据您的说明,您将通过 Loadbalancer 公开服务 - 作为服务类型的一部分创建。 When you modify the target group lister port, it breaks the communication between your Ingress and this service Loadbalancer because as per your Kubernetes service manifests, desired states of the Loadbalancer listener is 50051.当您修改目标组列表器端口时,它会中断您的 Ingress 和此服务负载均衡器之间的通信,因为根据您的 Kubernetes 服务清单,负载均衡器侦听器的所需状态是 50051。

You can follow the order below to get the sample grpc app deployed.您可以按照以下顺序部署示例 grpc 应用程序。

https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/grpc https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/grpc

  1. Deploy the fortune-teller app部署算命应用
$ kubectl create -f app.yaml
  1. Deploy the service as type: ClusterIP将服务部署为类型:ClusterIP
 $ kubectl create -f svc.yaml
  1. Deploy the nginx-ingress controller部署 nginx-ingress controller
 $ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v0.34.1/deploy/static/provider/do/deploy.yaml
  1. Deploy the ingress resources部署入口资源
$ kubectl create -f ingress.yaml
  1. Finally, add a host entry to spoof your domain name For eg: "fortune-teller.stack.build", with the A record of your Ingress LB.最后,添加一个主机条目来欺骗您的域名 例如:“fortune-teller.stack.build”,带有您的 Ingress LB 的 A 记录。

  2. Validation验证

$ grpcurl --insecure fortune-teller.stack.build:443 build.stack.fortune.FortuneTeller/Predict { "message": "Fremen add life to spice!" }

In a nutshell, here is the workflow.简而言之,这是工作流程。

GRPC Request --> Nginx Ingress NLB – > Backend Service (Cluster IP) --> Application pods GRPC 请求 --> Nginx 入口 NLB --> 后端服务(集群 IP) --> 应用程序 pod

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM