kubernetes 如何使用各种Istio端口?

x33g5p2x  于 2022-11-02  发布在  Kubernetes
关注(0)|答案(3)|浏览(191)

问题

我正在尝试学习Istio,并且正在设置我的Istio入口网关。当我进行设置时,有以下端口选项(如此处所示):

  • 端口
  • 节点连接埠
  • 目标端口

NodePort对我来说是有意义的。这是入口网关将在Kubernetes集群中的每个工作节点上侦听的端口。到达那里的请求将使用入口网关CRD路由到Kubernetes集群。
在示例中,Port通常被设置为与其匹配的流量的公共端口(80用于http,443用于https等)。我不明白Istio需要这个端口做什么,因为我没有看到任何流量使用NodePort以外的任何端口。
TargetPort对我来说是一个谜。我看过一些关于它的文档,适用于普通的Istio网关(上面说它只适用于使用ServiceEntries的情况),但没有任何文档对入口网关有意义。

我的问题是,与入口网关(不是普通网关)相关的TargetPort是什么?

更多详细信息

最后,我试图调试为什么我的入口流量得到“连接被拒绝”的响应。
我使用以下配置设置了我的Istio Operator following this tutorial

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio-controlplane
  namespace: istio-system
spec:
  components:    
    ingressGateways:
    - enabled: true
      k8s:
        service:
          ports:
          - name: http2
            port: 80
            nodePort: 30980            
        hpaSpec:
          minReplicas: 2
      name: istio-ingressgateway
    pilot:
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
  profile: default

我从我的配置中省略了TargetPort,因为我发现这个发行说明说Istio将选择安全的默认值。
我试着按照this tutorial中的步骤操作。
我尝试了该教程中指出的curl命令:

curl -s -I -H Host:httpbin.example.com "http://10.20.30.40:30980/status/200"

我得到了Failed to connect to 10.20.30.40 port 30980: Connection refused的响应
但是我可以ping 10.20.30.40,并且获取节点端口的命令返回30980
所以我开始想,也许这是一个问题,与TargetPort设置,我不明白。
istiod日志的检查提示我可能是在正确的轨道上。

kubectl logs -n istio-system -l app=istiod

在日志中我发现:

warn    buildGatewayListeners: skipping privileged gateway port 80 for node istio-ingressgateway-dc748bc9-q44j7.istio-system as it is an unprivileged pod
warn    gateway has zero listeners for node istio-ingressgateway-dc748bc9-q44j7.istio-system

所以,如果你能做到这一点,那么哇!我感谢你阅读这一切。如果你对我需要设置TargetPort有任何建议,或者如果我错过了其他东西,我很乐意听到它。

64jmpszr

64jmpszr1#

端口、节点端口和目标端口不是Istio的概念,而是Kubernetes的概念,更具体地说,是Kubernetes服务的概念,这就是为什么在Istio操作员API中没有详细描述的原因。
Istio运营商API提供了配置入口网关(Kubernetes)服务的选项。
有关这些概念的说明,请参阅Kubernetes Service的文档。
另请参阅Difference between targetPort and port in Kubernetes Service definition
因此,目标端口是入口网关的Pod的容器接收它们的业务的地方。
因此,我认为端口和目标端口的配置是特定于应用程序的,80-〉8080的Map或多或少是任意的,即应用程序的“决定”。
其他详细信息:
Istio操作员描述入口网关,入口网关本身由Kubernetes服务和Kubernetes部署组成。通常它部署在istio-system中。您可以检查istio-ingressgateway的Kubernetes服务,它将符合该YAML的规范。
因此,Istio入口网关实际上是在与其容器对话。然而,这主要是Istio入口网关的实现细节,与您为应用定义的服务和虚拟服务无关。
入口网关本身是一项服务,它在您定义的端口(即80)上接收通信,并将其转发到其容器上的8080。然后,它根据网关和虚拟服务配置的规则处理通信,并将其发送到应用程序的服务。

8ftvxx2r

8ftvxx2r2#

我仍然不太明白TargetPort在做什么,但是我已经让教程工作了。
我返回到一个卸载的Istio(通过删除操作员配置,然后删除istio命名空间)。然后我重新安装它,但我取出了我的配置中指定节点端口的部分。
然后我运行了一个kubectl get namespace istio-ingressgateway -o yaml -n istio-system,它显示了istio入口网关使用什么作为端口的默认值,然后我更新了我的yaml以匹配操作符(除了我想要的自定义NodePort),这就成功了。
最后,yaml看起来是这样的:

apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
metadata:
  name: istio-controlplane
  namespace: istio-system
spec:
  components:    
    ingressGateways:
    - enabled: true
      k8s:
        service:
          ports:
          - name: status-port
            nodePort: 32562
            port: 15021
            protocol: TCP
            targetPort: 15021
          - name: http2
            nodePort: 30980
            port: 80
            protocol: TCP
            targetPort: 8080
          - name: https
            nodePort: 32013
            port: 443
            protocol: TCP
            targetPort: 8443           
        hpaSpec:
          minReplicas: 2
      name: istio-ingressgateway
    pilot:
      enabled: true
      k8s:
        hpaSpec:
          minReplicas: 2
  profile: default

我仍然想了解TargetPort在做什么。所以如果有人能回答这个问题(同样,在Istio入口网关服务的上下文中(而不是istio网关)),那么我会接受这个答案。

rur96b6h

rur96b6h3#

为istio网关配置一个服务将创建一个具有给定端口配置的kubernetes服务,这(正如前面提到的另一个答案)不是一个istio概念,而是一个kubernetes概念,因此我们需要了解一下底层的kubernetes机制。
默认情况下,将创建的服务类型为LoadBalancer。此外,云提供商将创建一个外部LoadBalancer,该LoadBalancer将通过特定端口到达它的流量转发到群集。

$ kubectl get svc -n istio-system
NAME                   TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)                  
istio-ingressgateway   LoadBalancer   10.107.158.5   1.2.3.4       15021:32562/TCP,80:30980/TCP,443:32013/TCP

您可以看到服务的内部ip以及外部负载平衡器的外部ip,例如,在PORT(S)列中,您的端口80被Map到端口30980。在后台,kube-proxy接受您的配置,并配置一组iptables链,以设置到ingress-gateway pod的流量路由。
如果你有kubernetes主机的访问权限,你可以使用iptables命令来检查这些主机。

$ iptables -t nat -nL KUBE-SERVICES | grep ingressgateway
target                     prot opt source        destination
KUBE-SVC-TFRZ6Y6WOLX5SOWZ  tcp  --  0.0.0.0/0     10.107.158.5    /* istio-system/istio-ingressgateway:status-port cluster IP */ tcp dpt:15021
KUBE-FW-TFRZ6Y6WOLX5SOWZ   tcp  --  0.0.0.0/0     1.2.3.4         /* istio-system/istio-ingressgateway:status-port loadbalancer IP */ tcp dpt:15021
KUBE-SVC-G6D3V5KS3PXPUEDS  tcp  --  0.0.0.0/0     10.107.158.5    /* istio-system/istio-ingressgateway:http2 cluster IP */ tcp dpt:80
KUBE-FW-G6D3V5KS3PXPUEDS   tcp  --  0.0.0.0/0     1.2.3.4         /* istio-system/istio-ingressgateway:http2 loadbalancer IP */ tcp dpt:80
KUBE-SVC-7N6LHPYFOVFT454K  tcp  --  0.0.0.0/0     10.107.158.5    /* istio-system/istio-ingressgateway:https cluster IP */ tcp dpt:443
KUBE-FW-7N6LHPYFOVFT454K   tcp  --  0.0.0.0/0     1.2.3.4         /* istio-system/istio-ingressgateway:https loadbalancer IP */ tcp dpt:443

您将看到基本上有六个链,您定义的每个端口有两个链:8043315021(位于最右侧)。
KUBE-SVC-*用于集群内部流量,KUBE-FW-*用于集群外部流量。|因此,到达节点的网络接口的流量例如是目的地1.2.3.4:80。现在,您可以沿着该链向下,在我的示例中为KUBE-FW-G6D3V5KS3PXPUEDS

iptables -t nat -nL KUBE-FW-G6D3V5KS3PXPUEDS | grep KUBE-SVC
target                     prot opt source       destination
KUBE-SVC-LBUWNFSUU3FNPZ7L  all  --  0.0.0.0/0    0.0.0.0/0    /* istio-system/istio-ingressgateway:http2 loadbalancer IP */

也跟着那个

$ iptables -t nat -nL KUBE-SVC-LBUWNFSUU3FNPZ7L | grep KUBE-SEP
target                     prot opt source       destination
KUBE-SEP-RZL3ZLWSG2M7ZJYD  all  --  0.0.0.0/0    0.0.0.0/0     /* istio-system/istio-ingressgateway:http2 */ statistic mode random probability 0.50000000000
KUBE-SEP-F7W3YTTYPP5NEPJ7  all  --  0.0.0.0/0    0.0.0.0/0     /* istio-system/istio-ingressgateway:http2 */

您可以看到服务端点,它们以50:50的比例进行循环负载平衡,最后(选择其中一个):

$ iptables -t nat -nL KUBE-SEP-RZL3ZLWSG2M7ZJYD | grep DNAT
target     prot opt source       destination
DNAT       tcp  --  0.0.0.0/0    0.0.0.0/0    /* istio-system/istio-ingressgateway:http2 */ tcp to:172.17.0.4:8080

在那里它们最终被DNATed到172.17.0.4:8080,这是一个istio-ingressgateway pod ip和端口8080的ip。
如果您无法访问主机/不在公共云环境中运行,您将没有外部负载平衡器,因此您将找不到任何KUBE-FW-*链(服务中的EXTERNAL-IP也将保留在<pending>中)。在这种情况下,您将使用<nodeip>:<nodeport>从外部访问集群,运行iptables -t nat -nL KUBE-NODEPORTS | grep istio-ingressgateway,它也会显示三个KUBE-SVC-*链,您可以按照上面所示的方法一直跟踪到DNAT。
所以目标端口(如8080)用于在kubernetes中配置网络,istio也使用它来定义ingressgateway pod绑定到哪些端口。(80808443)作为容器端口。请将它们更改为(大于1000),它们将相应地更改。接下来,您将应用Gatewayspec.servers,其中定义这些端口8080,8443以配置envoy(= istio-ingressgateway,你用spec.selector定义的那个)来监听那些端口,还有一个VirtualService来定义由谁来处理接收到的请求。
为什么初始配置不起作用?如果省略targetport,istio将绑定到您定义的端口(80)。这要求istio以root身份运行,否则ingressgateway无法绑定到低于1000的端口。您可以通过在operator中设置values.gateways.istio-ingressgateway.runAsRoot=true来更改它,也可以参考你提到的版本说明。2在这种情况下,从上面来的整个流量看起来完全一样,不同之处在于入口网关pod将绑定到80,443而不是8080,8443,并且DNAT将绑定到<pod-ip>:(80|443)而不是<pod-ip:(8080|8443)>
所以你基本上只是误解了发行说明:如果您不以root身份运行istio-ingressgateway pod,则必须定义targetPort或省略整个k8s.service覆盖(在这种情况下,istio将自行选择安全矶钓)。
请注意,我将grep艾德为KUBE-SVCKUBE-SEPDNAT。总会有一堆KUBE-MARK-MASQKUBE-MARK-DROP现在并不重要。如果你想了解更多关于这个主题的信息,有一些关于这个主题的很棒的文章,比如this one

相关问题