网关端口定义如何工作?

How does the Gateway port definition work?

我在 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 pods 的 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 pods 的 targetPort 是 8443 那么网关定义是如何工作的,它将端口号定义为 443?

如前所述

port: The port of this service

targetPort: The target port on the pod(s) to forward traffic to

据我所知 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 检查您的入口网关 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。

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