在 AWS EKS 和 Istio Ingress 上使用 GRPC 的 SSL 提供 StatusCode.UNAVAILABLE

Posted

技术标签:

【中文标题】在 AWS EKS 和 Istio Ingress 上使用 GRPC 的 SSL 提供 StatusCode.UNAVAILABLE【英文标题】:SSL with GRPC on AWS EKS and Istio Ingress gives StatusCode.UNAVAILABLE 【发布时间】:2021-01-11 16:58:30 【问题描述】:

我正在使用 AWS EKS 服务(K8S 版本 1.17)运行一个 kubernetes 集群,并在其上安装了 Istio (1.7.1) 作为 Operator 安装。

我一直在运行这些服务,因为它们工作正常,而且我正在运行 Istio Ingress Gateway 作为入口服务,使用 AWS NLB 发布,在 Istio Ingress Gateway 上带有以下注释:

metadata:
  annoations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "tcp"
    service.beta.kubernetes.io/aws-load-balancer-internal: "false"
    service.beta.kubernetes.io/aws-load-balancer-ssl-cert: "redacted arn"
    service.beta.kubernetes.io/aws-load-balancer-ssl-ports: "https"

这成功创建了具有 4 个侦听器(根据 Istio 入口定义)的 NLB,其中 443 使用提供的证书运行 TLS。

在它后面的网关配置如下:

apiVersion: networking.istio.io/v1beta1
kind: Gateway
metadata:
  name: service-gateway
  namespace: istio-system
spec:
  selector:
    istio: ingressgateway
  servers:
    - port:
        number: 80
        name: grpc-plain
        protocol: GRPC
      hosts:
        - redacted
    - port:
        number: 443
        name: grpc-tls
        protocol: GRPC
      hosts:
        - redacted
---
apiVersion: networking.istio.io/v1beta1
kind: VirtualService
metadata:
  name: service-vservice
  namespace: app
spec:
  gateways:
  - istio-system/service-gateway
  hosts:
  - redacted
  http:
  - route:
    - destination:
        host: service
        port:
          number: 8000

但是,虽然普通端口 (80) 与负载平衡器配合得很好,但 SSL/TLS 端口 443 使用任何语言(使用 C、C++、Python 测试)都会出现以下错误:

grpc._channel._InactiveRpcError: <_InactiveRpcError of RPC that terminated with:
    status = StatusCode.UNAVAILABLE
    details = "failed to connect to all addresses"
    debug_error_string = ""created":"@1601027790.018488379","description":"Failed to pick subchannel","file":"src/core/ext/filters/client_channel/client_channel.cc","file_line":4089,"referenced_errors":["created":"@1601027790.018476348","description":"failed to connect to all addresses","file":"src/core/ext/filters/client_channel/lb_policy/pick_first/pick_first.cc","file_line":393,"grpc_status":14]"
>

例如,Python 客户端已初始化如下:

import grpc
from service_pb2_grpc import ServiceStub

creds = grpc.ssl_channel_credentials()

with grpc.secure_channel(url, creds) as channel:
    grpc_client = ServiceStub(channel)

在使用简单客户端时出现此错误,我做错了什么?

【问题讨论】:

【参考方案1】:

根据this有关在 AWS 上使用 GRPC 的文章,看来在 AWS 上使用 GRPC 是一项具有挑战性的任务。

还有一个article 介绍了如何在 AWS 上为 GRPC 创建负载平衡器。

事实是这样——gRPC 不能与 AWS 负载均衡器一起正常工作。

接下来是使用 envoy 的解决方法:

如何使用 Envoy 在 AWS 上对 gRPC 进行负载平衡

那么这里的解决方案是什么?我们决定使用第三方软件进行负载平衡。在本例中,我们使用了Envoy(用于 AWS 负载均衡器第 7 层)。这是 Lyft 开发的开源软件。

【讨论】:

实际上我发现所有用于 GRPC 的基于 C 的库都需要将 ALPN 策略设置为某些东西(最好是 HTTP2Preferred)才能正常工作,而本地的则不需要(例如 Swift、Go)。很奇怪……

以上是关于在 AWS EKS 和 Istio Ingress 上使用 GRPC 的 SSL 提供 StatusCode.UNAVAILABLE的主要内容,如果未能解决你的问题,请参考以下文章

AWS eks绑定alb 使用aws-load-balancer-controller(Ingress Controller)提供服务

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

Terraform AWS EKS ALB Kubernetes Ingress 不会创建侦听器或目标组

EKS 中的 AWS 跨账户 Loki promtail 设置

kubectl 等待 AWS EKS 上的服务公开 .status.loadBalancer.ingress 字段中报告的 Elastic Load Balancer (ELB) 地址

我可以将Ingress控制器指向AWS S3等外部服务