当我在 GKE 中将 NodePort 服务指定为 Ingress 后端时,我得到了两个后端

When I specify NodePort service as Ingress backend in GKE, I get two backends

--概览

我在 GKE 上自定义安装了 istio (type=nodeport)。安装命令如下

istioctl install --set profile=default --set values.gateways.istio-ingressgateway.type=NodePort

我正在构建 Ingress 并将 NodePort 服务指定为后端。我发现即使我指定了 NodePort,GCP 也将另一个后端指定为默认设置。因此,我无法通过 TCP/IP 连接到 GCP LoadBalancer。如果我将相同的端口设置为 pod 的 readinessprobe 入口等,健康检查也会在那里。 有什么办法可以解决吗?

--详情

Detail view of LB

# This is a value that is automatically set by istio
$ k get svc istio-ingressgateway -n istio-system -o yaml
  ports:
  - name: status-port
    nodePort: 32476
    port: 15021
    protocol: TCP
    targetPort: 15021
  - name: http2
    nodePort: 32241
    port: 80
    protocol: TCP
    targetPort: 8080
  - name: https
    nodePort: 31739
    port: 443
    protocol: TCP
    targetPort: 8443
  - name: tcp-istiod
    nodePort: 32488
    port: 15012
    protocol: TCP
    targetPort: 15012
  - name: tls
    nodePort: 32741
    port: 15443
    protocol: TCP
    targetPort: 15443
$ k get po istio-ingressgateway-6f8bbbbd8c-qmkln -n istio-system -o yaml
:
    readinessProbe:
      failureThreshold: 30
      httpGet:
        path: /healthz/ready
        port: 15021
        scheme: HTTP
      initialDelaySeconds: 1
      periodSeconds: 2
      successThreshold: 1
      timeoutSeconds: 1
# 
spec:
  rules:
  - host: www.custom.com
    http:
      paths:
      - backend:
          serviceName: istio-ingressgateway
          servicePort: 80
      - backend:
          serviceName: istio-ingressgateway
          servicePort: 15021
istio-system   istio-ingressgateway   NodePort    10.47.13.185   <none>        15021:31761/TCP,80:31561/TCP,443:31257/TCP,15012:31841/TCP,15443:32172/TCP   9h

我把这个答案分为几部分:

  • 使用 GKE 创建 Ingress 资源时的两个后端。
  • 问题中的入口定义。
  • Cloud 装甲与 Istio 整合。

使用 GKE

创建 Ingress 资源时的两个后端

这是按预期工作的,因为使用 GKE 创建的 Ingress 将有 2 个后端:

  • YAML 清单中指定的。
  • 默认后端:default-http-backend

例如,您可以按照以下步骤操作:

  • $ kubectl create deployment nginx --image=nginx
  • $ kubectl expose deployment nginx --port=80 --type=NodePort
  • nginx 创建一个 Ingress 资源,但具有 hello 路径(用于示例目的)

之后您应该会看到类似的设置:

第一个后端服务正在使用实例组将请求发送到与 Ingress 资源不匹配的默认后端。

第二个后端服务正在使用 NEG(网络端点组)发送与 Ingress 资源匹配的请求(在本例中为 nginx Deployment)。

我已将红色方块标记为将其与 Kubernetes 资源“连接”(查看端口):

  • $ kubectl get svc nginx
NAME    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.20.6.229   <none>        80:32612/TCP   51m
  • $ kubectl get svc -n kube-system default-http-backend
NAME                   TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
default-http-backend   NodePort   10.20.15.39   <none>        80:30603/TCP   121m

问题中的入口定义

问题 is/was 中包含的 Ingress 定义部分以引用具有 2 个不同后端的相同路径的方式创建:

    http:
      paths:
      - backend:
          serviceName: istio-ingressgateway
          servicePort: 80
      - backend:
          serviceName: istio-ingressgateway
          servicePort: 15021

上面的例子:

  • 有 2 个不同的后端。
  • 配置为2个不同的后端共享相同的路径。
  • 请求(如我所复制的那样)进入“15021”后端,仅用于健康检查。

要解决这个问题,您需要删除 15021 后端并使用 backendConfig 资源来配置健康检查和安全策略(稍后会详细介绍)。

A side note!

The YAML manifest is using and old and soon to be deprecated way to describe Ingress. Please refer to this documentation for more reference:


将 Cloud Armor 与 Istio 集成

您可以通过以下方式将 Cloud Armor 与 Istio 结合使用:

  • 创建安全策略。
  • 创建 backendConfig 作为 Istio Service 的先决条件。
  • 安装 Istio 并修改其 Service
  • 创建 Ingress 资源以指向 istio-ingressgateway
  • 用例子测试。

创建安全策略

出于示例目的,可以创建仅阻止单个 IP 地址的安全策略。可以通过 gcloudCloud Console (Web UI):

让我们假设创建了名为 deny-single 的安全策略来阻止单个 IP 地址。

创建 backendConfig 作为 Istio Service 的先决条件。

您将需要创建一个 backendConfig 来配置运行状况检查并强制执行安全策略:

apiVersion: cloud.google.com/v1
kind: BackendConfig
metadata:
  name: ingress-backendconfig
  namespace: istio-system
spec:
  healthCheck:
    requestPath: /healthz/ready
    port: 15021
    type: HTTP
  securityPolicy:
    name: deny-single # <-- IMPORTANT

安装 Istio 并修改其 Service

您需要在 istio-ingressgatewayService 中添加以下注释 :

    cloud.google.com/backend-config: '{"default": "ingress-backendconfig"}'
    cloud.google.com/neg: '{"ingress":true}'

此注释将通知 GCP 要应用的安全策略以及将流量传递到 istio-ingressgateway 所需的健康检查。

创建一个 Ingress 资源指向 istio-ingressgateway

将请求从 HTTP(S) Load Balancer 发送到 istio-ingressgateway 的基本 Ingress 定义如下:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: istio-ingress
  namespace: istio-system
spec:
  rules:
  - http:
      paths:
      - path: /*
        pathType: ImplementationSpecific
        backend:
          service:
            name: istio-ingressgateway
            port:
              number: 80

用例子测试

要检查设置是否正常工作,您可以生成 Bookinfo Application

使用 2 个不同的 IP 地址进行测试:

  • $ curl ifconfig.me
217.AAA.BBB.CCC
  • $ curl 34.XXX.YYY.ZZZ/productpage
<!doctype html><meta charset="utf-8"><meta name=viewport content="width=device-width, initial-scale=1"><title>403</title>403 Forbidden%
  • $ curl ifconfig.me
94.EEE.FFF.GGG
  • $ curl 34.XXX.YYY.ZZZ/productpage
<html>
  <head>
    <title>Simple Bookstore App</title>
<-- REDACTED --> 

A side note!

The "closed port" that you've received could be related to the fact that istio-ingressgateway was configured to listen on specific path like /productpage and not /. (if the request was specifically targeted to port 80 instead of 15021)


其他资源: