【问题标题】:How does the Gateway port definition work?网关端口定义如何工作?
【发布时间】:2021-03-04 18:32:15
【问题描述】:

我在 AKS 上有一个带有默认入口网关的示例 istio 集群。一切都按预期工作我只是想了解如何。网关定义如下:

apiVersion: networking.istio.io/v1alpha3
kind: Gateway
metadata:
  name: my-gateway
  namespace: some-config-namespace
spec:
  selector:
    app: istio-ingressgateway
  servers:
  - port:
      number: 80
      name: http
      protocol: HTTP
    hosts:
    - uk.bookinfo.com
    - eu.bookinfo.com
    tls:
      httpsRedirect: true # sends 301 redirect for http requests
  - port:
      number: 443
      name: https-443
      protocol: HTTPS
    hosts:
    - uk.bookinfo.com
    - eu.bookinfo.com
    tls:
      mode: SIMPLE # enables HTTPS on this port
      serverCertificate: /etc/certs/servercert.pem
      privateKey: /etc/certs/privatekey.pem

通过https://uk.bookinfo.com 访问该站点可以正常工作。但是,当我查看进入 ingressgateway pod 的 LB 和服务时,我看到了:

LB-IP:443 -> CLUSTER-IP:443 -> istio-ingressgateway:8443
kind: Service
spec:
  ports:
    - name: http2
      protocol: TCP
      port: 80
      targetPort: 8080
      nodePort: 30804
    - name: https
      protocol: TCP
      port: 443
      targetPort: 8443
      nodePort: 31843
  selector:
    app: istio-ingressgateway
    istio: ingressgateway
  clusterIP: 10.2.138.74
  type: LoadBalancer

由于 istio-ingressgateway pod 的 targetPort 是 8443,那么将端口号定义为 443 的网关定义如何工作?

【问题讨论】:

    标签: kubernetes istio envoyproxy


    【解决方案1】:

    如上所述here

    port:此服务的端口

    targetPort:Pod 上将流量转发到的目标端口

    据我所知,targetPort: 8443 指向 envoy sidecar,所以如果我理解正确,envoy 可以在 8080 上监听 http,在 8443 上监听 https。

    envoy documentation中有一个例子。

    原来是这样的:

    LB-IP:443 -> CLUSTER-IP:443 -> istio-ingressgateway:443 -> envoy-sidecar:8443
    LB-IP:80 -> CLUSTER-IP:80 -> istio-ingressgateway:80 -> envoy-sidecar:8080
    

    例如,对于 http,如果您在未配置任何网关的情况下使用 netstat 检查 ingress-gateway pod,则端口 8080 上没有任何监听:

    kubectl exec -ti istio-ingressgateway-86f88b6f6-r8mjt -n istio-system -c istio-proxy -- /bin/bash
    istio-proxy@istio-ingressgateway-86f88b6f6-r8mjt:/$ netstat -lnt | grep 8080
    

    让我们现在用下面的 yaml 创建一个 http 网关。

    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: istio-gw
      namespace: istio-system
    spec:
      selector:
        istio: ingressgateway
      servers:
      - port:
          number: 80
          name: http
          protocol: HTTP
        hosts:
        - "*"
    

    然后再次检查 netstat:

    kubectl exec -ti istio-ingressgateway-86f88b6f6-r8mjt -n istio-system -c istio-proxy -- /bin/bash
    istio-proxy@istio-ingressgateway-86f88b6f6-r8mjt:/$ netstat -lnt | grep 8080
    tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN
    

    如您所见,我们在端口 80 上配置了网关,但在 ingressgateway 内部我们可以看到它正在侦听端口 8080。

    【讨论】:

    • 正如我所指出的,服务 targetPort 是 8443 那么 LB 如何正确指向入口网关 pod 上的 443?
    • @Chaos 有一个来自 istio dev john howard 的 comment,端口用于使其外部可见,而 targetPort 用于内部避免 root。当 lb 由它使用端口的任何云创建时,targetPort 是服务将向其发送请求的端口,您的 pod 将在该端口上进行侦听。因此,您的请求与 lb:443 一起使用,该服务具有端口:443 和目标端口:8443 到 ingress-gateway-pod,它在 8443 上侦听,因为里面有 envoy sidecar。我是这么理解的。
    • 感谢@Jakub,这很有趣。我想知道它是如何知道例如 8443 上的请求实际上来自 443,然后在网关定义中。如果您知道这是如何工作的,我们将不胜感激,但无论如何我都会将您的答案标记为正确。
    • AFAIK 这就是使用 iptables 配置的方式。类似这种解决方法here。看看thisthis 的文章。
    【解决方案2】:

    我觉得 istio 的这种机制有点混乱。
    在我的理解中,网关定义的端口应该是pod中listen的端口,然后服务决定暴露的端口。
    尽管目前的机制对用户来说很方便,但还是会有一些混乱和不确定性。
    如果 istio 想保留这个机制,我建议 istio 改进它。在创建网关的时候,关联的是ingress-svc而不是pod,然后明确定义端口为svc的端口。如果端口在svc中不存在,更新服务开启或者禁止创建网关

    【讨论】:

    猜你喜欢
    • 2019-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-03
    • 2011-12-14
    • 2013-03-29
    • 2018-12-30
    相关资源
    最近更新 更多