如何通过 Kubernetes 服务(如网关 API)路由到特定的 pod

Ant*_*ony 9 kubernetes kubernetes-ingress kubernetes-pod

我在 Windows 的“Docker 桌面”上运行 Kubernetes。

我有一个用于部署的 LoadBalancer 服务,其中有 3 个副本。我想通过某种方式访问​​特定的 pod (例如通过 URL 路径:<serviceIP>:8090/pod1)

有没有办法实现这个用例?


部署.yaml:

apiVersion: v1
kind: Service
metadata:
  name: my-service1
  labels:
    app: stream
spec:
  ports:
  - port: 8090
    targetPort: 8090
    name: port8090
  selector:
    app: stream
  # clusterIP: None
  type: LoadBalancer
---
apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: stream-deployment
  labels:
    app: stream
spec:
  replicas: 3
  selector:
    matchLabels:
      app: stream
  strategy:
    type: Recreate
  template:
    metadata:
      labels:
        app: stream
    spec:
      containers:
      - image: stream-server-mock:latest
        name: stream-server-mock
        imagePullPolicy: Never
        env:
        - name: STREAMER_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: STREAMER_ADDRESS
          value: stream-server-mock:8090
        ports:
        - containerPort: 8090
Run Code Online (Sandbox Code Playgroud)

我的最终目标是实现 pod 的水平自动缩放。

应用程序如何设计/和工作到现在(没有 kubernetes):

有 3 个组件:REST-Server、Stream-Server(在不同端口的不同 JVM 上的本地 3 个实例)和 RabbitMQ。

1 - The client sends a request to "REST-Server" for a stream url.
2 - The REST-Server puts in the RabbitMQ queue.
3 - One of the Stream-Server picks it up and populates its IP and sends back to REST-Server through RabbitMQ.
4 - The client receives the IP and establishes a direct WS connection using the IP.
Run Code Online (Sandbox Code Playgroud)

我面临的问题是

1 - When the client requests for a stream IP, one of the pods (lets say POD1) picks it up and sends its URL (which is service URL, comes through LoadBalancer Service).
2 - Next time when the client tries to connect (WebSocket Connection) using the Service IP, it wont be the same pod which accepted the request.
Run Code Online (Sandbox Code Playgroud)

它应该是接受请求的同一个 pod,并且必须可以被客户端访问。

aer*_*ite 6

如果不需要使用部署,则可以使用StatefulSet

对于副本 3,您将有 3 个 pod 命名

  1. 流部署-0
  2. 流部署-1
  3. 流部署-2

您可以访问每个 pod $(podname).$(service name).$(namespace).svc.cluster.local

有关详细信息,请检查

您可能还想设置一个入口以从集群外部指向每个 pod。


Ala*_*aye 5

正如 aerokite 提到的,您可以使用 StatefulSets。但是,如果您不想修改部署,则可以简单地使用Headless Services。正如文档中所指定的:

对于无头服务,不会分配集群 IP。

对于定义选择器的无头服务,端点控制器在 API 中创建端点记录,并修改 DNS 配置以返回直接指向支持服务的 Pod 的记录(地址)。

这意味着每当您查询服务的 DNS 名称(即 my-svc.my-namespace.svc.cluster-domain.example)时,您得到的是所有 Pod IP 的列表(与您获取集群 IP)。然后,您可以使用自己的机制选择 Pod。

关于您的新问题,如果这是您唯一的问题,您可以使用会话关联性。如果您设置service.spec.sessionAffinityClientIP,那么来自特定客户端的连接每次都会始终转到同一个 Pod。您不需要进行其他修改,例如上面提到的无头服务。


Jun*_*aid 0

IMO,实现这一目标的唯一方法是:

  1. 不要使用具有 3 个副本的部署,而是使用 3 个部署,每个部署有 1 个副本(或者仅创建 Pod);部署1 -> pod1,部署2 -> pod2,部署3 -> pod3
  2. 将所有部署公开在单独的服务上,service1 -> 部署1、服务2 -> 部署2、服务3 -> 部署3
  3. 使用每个部署的服务创建入口资源并路由到每个 Pod。例如:
    • 入口 URL/service1
    • 入口 URL/service2
    • 入口 URL/service3