Istio (1.0) 内部 ReplicaSet 路由 - 支持 Kubernetes 部署中 Pod 之间的流量

Rob*_*man 5 jgroups infinispan kubernetes istio envoyproxy

Istio 如何支持同一服务中的 Pod 之间基于 IP 的路由(或者更具体地说是 ReplicaSet)?

我们想在 Istio 网格中部署一个副本 > 1 的 Tomcat 应用程序。该应用程序运行 Infinispan,它使用 JGroups 来整理通信和集群。JGroups 需要识别其集群成员,为此需要使用 KUBE_PING(JGroups 的 Kubernetes 发现协议)。它将通过类似于kubectl get pods的查找来咨询 K8S API 。集群成员既可以是其他服务中的 pod,也可以是同一服务/部署中的 pod。

尽管我们的问题是由相当具体的需求驱动的,但该主题是通用的。我们如何让 pod 能够在副本集内相互通信?

示例:作为展示,我们部署了演示应用程序https://github.com/jgroups-extras/jgroups-kubernetes。相关的东西是:

apiVersion: v1
items:
- apiVersion: extensions/v1beta1
  kind: Deployment
  metadata:
    name: ispn-perf-test
    namespace: my-non-istio-namespace
  spec:
    replicas: 3
< -- edited for brevity -- >
Run Code Online (Sandbox Code Playgroud)

没有 Istio情况下运行,三个 Pod 会相互找到并形成集群。在my-istio-namespace 中使用 Istio部署相同的内容并添加基本服务定义:

kind: Service
apiVersion: v1
metadata:
  name: ispn-perf-test-service
  namespace: my-istio-namespace
spec:
  selector:
    run : ispn-perf-test
  ports:
  - protocol: TCP
    port: 7800
    targetPort: 7800
    name: "one"
  - protocol: TCP
    port: 7900
    targetPort: 7900
    name: "two"
  - protocol: TCP
    port: 9000
    targetPort: 9000
    name: "three"
Run Code Online (Sandbox Code Playgroud)

请注意,下面的输出很宽 - 您可能需要向右滚动才能获取 IP

kubectl get pods -n my-istio-namespace -o wide
NAME                                                READY     STATUS    RESTARTS   AGE       IP            NODE
ispn-perf-test-558666c5c6-g9jb5                     2/2       Running   0          1d        10.44.4.63    gke-main-pool-4cpu-15gb-98b104f4-v9bl
ispn-perf-test-558666c5c6-lbvqf                     2/2       Running   0          1d        10.44.4.64    gke-main-pool-4cpu-15gb-98b104f4-v9bl
ispn-perf-test-558666c5c6-lhrpb                     2/2       Running   0          1d        10.44.3.22    gke-main-pool-4cpu-15gb-98b104f4-x8ln

kubectl get service ispn-perf-test-service -n my-istio-namespace
NAME                     TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
ispn-perf-test-service   ClusterIP   10.41.13.74   <none>        7800/TCP,7900/TCP,9000/TCP   1d
Run Code Online (Sandbox Code Playgroud)

https://istio.io/help/ops/traffic-management/proxy-cmd/#deep-dive-into-envoy-configuration 的指导下,让我们看看其中一个 Pod 的结果 Envoy conf:

istioctl proxy-config listeners ispn-perf-test-558666c5c6-g9jb5 -n my-istio-namespace
ADDRESS          PORT      TYPE
10.44.4.63       7900      TCP
10.44.4.63       7800      TCP
10.44.4.63       9000      TCP
10.41.13.74      7900      TCP
10.41.13.74      9000      TCP
10.41.13.74      7800      TCP
< -- edited for brevity -- >
Run Code Online (Sandbox Code Playgroud)

Istio 文档将上述侦听器描述为

从侦听器接收相关 IP:PORT 对的出站非 HTTP 流量 0.0.0.0_15001

这一切都是有道理的。pod ispn-perf-test-558666c5c6-g9jb5可以在 10.44.4.63 上访问自身,通过 10.41.13.74 访问服务。但是……如果 pod 将数据包发送到 10.44.4.64 或 10.44.3.22 呢?这些 IP 不存在于侦听器中,因此对于ispn-perf-test-558666c5c6-g9jb5 而言,两个“兄弟”pod 无法访问。

Istio 今天能支持这个吗——那怎么支持?

Fra*_*k B 2

你是对的,HTTP 路由仅支持本地访问或通过服务名称或服务 VIP 进行远程访问。

也就是说,对于上面的特定示例,其中服务端口被命名为“一”、“二”、“三”,路由将是纯 TCP,如此处所述。因此,你的例子应该有效。Pod ispn-perf-test-558666c5c6-g9jb5 可以在 10.44.4.63 上到达自身,其他 Pod 可以在 10.44.4.64 和 10.44.3.22 上到达。

如果您将端口重命名为“http-one”、“http-two”和“http-三”,则 HTTP 路由将启动,并且 RDS 配置将限制远程调用为使用可识别服务域的远程调用。

要查看 RDF 配置中的差异,请查看以下命令在端口命名为“one”以及更改为“http-one”时的输出。

istioctl proxy-config routes ispn-perf-test-558666c5c6-g9jb5 -n my-istio-namespace  --name 7800 -o json
Run Code Online (Sandbox Code Playgroud)

对于名为“one”的端口,它将不返回任何路由,因此 TCP 路由将适用,但在“http-one”情况下,路由将受到限制。

我不知道是否有办法在 HTTP 情况下将额外的远程 Pod IP 地址添加到 RDS 域。我建议打开一个 Istio 问题,看看是否可行。