如何通过 Kubernetes 服务(如网关 API)路由到特定的 pod
Posted
技术标签:
【中文标题】如何通过 Kubernetes 服务(如网关 API)路由到特定的 pod【英文标题】:How to Route to specific pod through Kubernetes Service (like a Gateway API) 【发布时间】:2020-01-20 06:08:00 【问题描述】:我在 Windows 的“Docker Desktop”上运行 Kubernetes。
我有一个用于具有 3 个副本的部署的 LoadBalancer 服务。 我想通过某种方式访问 SPECIFIC pod (例如通过 URL 路径::8090/pod1)。
有没有办法实现这个用例?
deployment.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
我的最终目标是实现 pod 的水平自动缩放。
到目前为止,应用程序的设计/工作方式(没有 kubernetes):
有 3 个组件:REST-Server、Stream-Server(3 个实例 本地在不同端口上的不同JVM上)和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.
我面临的问题是:
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.
它应该与接受请求的 pod 相同,并且必须可供客户端访问。
【问题讨论】:
我已经更新了问题 【参考方案1】:如果您不需要使用部署,您可以使用StatefulSets。
对于副本 3,您将拥有 3 个命名的 pod
-
流部署-0
流部署-1
流部署-2
您可以通过$(podname).$(service name).$(namespace).svc.cluster.local
访问每个 pod
详情请查看this
您可能还想设置一个入口,以从集群外部指向每个 pod。
【讨论】:
在auto-scaling的情况下,我不认为有动态命名pod的机制。 我打算在上面使用 HPA。这是我的最终目标。【参考方案2】:正如 aerokite 所述,您可以使用 StatefulSets。但是,如果您不想修改您的部署,您可以简单地使用Headless Services。如文档中所述:
对于无头服务,不分配集群 IP。
对于定义选择器的无头服务,端点控制器 在 API 中创建 Endpoints 记录,并修改 DNS 配置返回直接指向 支持服务的 Pod。
这意味着每当您查询服务的 DNS 名称时(即 my-svc.my-namespace.svc.cluster-domain.example),您得到的是所有 Pod IP 的列表(与常规服务不同,您将获得集群 IP)。然后,您可以使用自己的机制选择您的 Pod。
关于您的新问题,如果这是您唯一的问题,您可以使用会话亲和性。如果您将service.spec.sessionAffinity
设置为ClientIP
,那么来自特定客户端的连接每次都将始终转到同一个 Pod。您不需要像上面提到的无头服务那样进行其他修改。
【讨论】:
@Anthony 我也更新了我的答案。您可以使用会话关联来解决您的问题。 我在 Windows 的本地环境中运行它。如果是“无头服务”,我如何从外部访问 pod 的 IP/服务? 我尝试了 sessionAffinity 和 Headless 服务。我没有按预期工作。我可能做得不对(我猜) 我已经用应用程序活动流程再次更新了问题。【参考方案3】:IMO,实现这一目标的唯一方法是:
-
不要使用具有 3 个副本的部署,而是使用具有 1 个副本的 3 个部署(或仅创建 pod);部署1 -> pod1,部署2 -> pod2,部署3 -> pod3
在单独的服务上公开所有部署,服务1 -> 部署1,服务2 -> 部署2,服务3 -> 部署3
为每个部署使用服务创建入口资源并路由到每个 pod。例如:
入口-url/service1
入口-url/service2
入口-url/service3
【讨论】:
您可以使用无头服务。我在回答中提到了细节。 @Junaid,在 Pod 自动伸缩的情况下将不起作用。 其他答案正在使用我不知道的更好的方法。 @AlassaneNdiaye 提到的sessionAffinity
看起来很相关,但不确定它是否满足您的 HPA 要求。以上是关于如何通过 Kubernetes 服务(如网关 API)路由到特定的 pod的主要内容,如果未能解决你的问题,请参考以下文章
是否有用于 Azure AKS(Azure kubernetes 服务)集群的 API 网关