入口仅将流量路由到一条路线

Ingress only routes traffic to one route

我有两个 pods,每个都有一个 LoadBalancer svc。每个服务的 IP 地址都有效。

我的第一个服务是:

apiVersion: v1
kind: Service
metadata:
  name: hello-world-1
spec:
  type: LoadBalancer
  selector:
    greeting: hello
    version: one
  ports:
  - protocol: TCP
    port: 60000
    targetPort: 50000

我的第二项服务是:

apiVersion: v1
kind: Service
metadata:
  name: hello-world-2
spec:
  type: LoadBalancer
  selector:
    greeting: hello
    version: two
  ports:
  - protocol: TCP
    port: 5000
    targetPort: 5000

我的入口是:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: gce
spec:
  defaultBackend:
    service:
      name: hello-world-1
      port:
        number: 60000
  rules:
  - http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: hello-world-1
            port:
              number: 60000
      - path: /v2
        pathType: ImplementationSpecific
        backend:
          service:
            name: hello-world-2
            port:
              number: 5000

只有第一条路线是这样的,当我把

<MY_IP>/v2

在 url 栏中我得到

Cannot GET /v2
  

如何配置入口,使其在未指定子路径时命中 / 路由,在指定 /v2 时命中 /v2 路由?

如果我把第一条路线改成

backend:
          service:
            name: hello-world-2
            port:
              number: 5000

并去掉第二个有效的。

但是如果我将路由更改为 /v2,它会停止工作吗?

***** 编辑 *****

按照这里的教程 ingress tut 我尝试更改 yaml,使不同的路由位于不同的端口,这会破坏它。有人知道为什么吗?

默认情况下,当您在集群中创建入口时,GKE 会创建一个 HTTP(S) 负载均衡器并将其配置为将流量路由到您的应用程序,如以下文档 [1] 中所述。因此,您不应该将服务配置为 LoadBalancer 类型,而是需要将它们配置为 NodePort。

在这里,您可以按照与您想要完成的目标类似的完整实施示例进行操作:

  1. 为每个版本创建在指定端口运行应用程序容器镜像的清单:
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web1
  namespace: default
spec:
  selector:
    matchLabels:
      run: web1
  template:
    metadata:
      labels:
        run: web1
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:1.0
        imagePullPolicy: IfNotPresent
        name: web1
        ports:
        - containerPort: 8000
          protocol: TCP

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web2
  namespace: default
spec:
  selector:
    matchLabels:
      run: web2
  template:
    metadata:
      labels:
        run: web2
    spec:
      containers:
      - image: gcr.io/google-samples/hello-app:2.0
        imagePullPolicy: IfNotPresent
        name: web2
        ports:
        - containerPort: 9000
          protocol: TCP
  1. 创建两个服务(每个版本一个)作为类型 NodePort。这一步的一个非常重要的注意事项是,指定的 targetPort 应该是应用程序正在侦听的那个,在我的例子中,两个服务都指向端口 8080,因为我使用的是同一个应用程序但不同的版本:
apiVersion: v1
kind: Service
metadata:
  name: web1
  namespace: default
spec:
  ports:
  - port: 8000
    protocol: TCP
    targetPort: 8080
  selector:
    run: web1
  type: NodePort

---
apiVersion: v1
kind: Service
metadata:
  name: web2
  namespace: default
spec:
  ports:
  - port: 9000
    protocol: TCP
    targetPort: 8080
  selector:
    run: web2
  type: NodePort
  1. 最后,您需要使用路径规则创建入口:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    kubernetes.io/ingress.class: gce
spec:
  defaultBackend:
    service:
      name: web1
      port:
        number: 8000
  rules:
  - http:
      paths:
      - path: /
        pathType: ImplementationSpecific
        backend:
          service:
            name: web1
            port:
              number: 8000
      - path: /v2
        pathType: ImplementationSpecific
        backend:
          service:
            name: web2
            port:
              number: 9000

如果你配置正确,命令 kubectl get ingress my-ingress 的输出应该是这样的:

NAME         CLASS    HOSTS   ADDRESS          PORTS   AGE
my-ingress   <none>   *       <External IP>    80      149m

并且,如果您的服务指向正确的端口,并且您的应用程序正在侦听这些端口,则对您的外部 IP 执行 curl(curl 外部 IP)应该得到你到你的应用程序的版本之一,这是我的示例输出:

Hello, world!
Version: 1.0.0
Hostname: web1-xxxxxxxxxxxxxx

对您的外部 ip /v2 执行 curl (curl External IP/v2) 应该可以让您进入应用程序的第二个版本:

Hello, world!
Version: 2.0.0
Hostname: web2-xxxxxxxxxxxxxx

[1] https://cloud.google.com/kubernetes-engine/docs/tutorials/http-balancer