简体   繁体   English

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

[英]How to Route to specific pod through Kubernetes Service (like a Gateway API)

I am running Kubernetes on "Docker Desktop" in Windows.我在 Windows 的“Docker Desktop”上运行 Kubernetes。

I have a LoadBalancer Service for a deployment which has 3 replicas.我有一个用于具有 3 个副本的部署的 LoadBalancer 服务。 I would like to access SPECIFIC pod through some means (such as via URL path: < serviceIP >:8090/pod1) .我想通过某种方式访问 SPECIFIC pod (例如通过 URL 路径:< serviceIP >:8090/pod1)

Is there any way to achieve this usecase?有没有办法实现这个用例?


deployment.yaml:部署.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

My end goal is to achieve horizontal auto-scaling of pods.我的最终目标是实现 pod 的水平自动缩放。

How Application designed/and works as of now (without kubernetes):到目前为止,应用程序是如何设计/和工作的(没有 Kubernetes):

There are 3 components: REST-Server, Stream-Server (3 instances locally on different JVM on different ports), and RabbitMQ.有 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.

The Problem what I face is :我面临的问题是

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.

It should be the same pod which accepted the request, and must be accessible by the client.它应该是接受请求的同一个 pod,并且必须可供客户端访问。

You can use StatefulSets if you are not required to use deployment.如果您不需要使用部署,则可以使用StatefulSets

For replica 3, you will have 3 pods named对于副本 3,您将有 3 个名为

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

You can access each pod as $(podname).$(service name).$(namespace).svc.cluster.local您可以通过$(podname).$(service name).$(namespace).svc.cluster.local访问每个 pod

For details, check this有关详细信息,请检查

You may also want to set up an ingress to point each pod from outside of the cluster.您可能还想设置一个入口以从集群外部指向每个 pod。

As mentioned by aerokite, you can use StatefulSets.正如 aerokite 所提到的,您可以使用 StatefulSets。 However, if you don't want to modify your deployments, you can simply use Headless Services .但是,如果您不想修改部署,则可以简单地使用Headless Services As specified in the documentation:如文档中所述:

For headless Services, a cluster IP is not allocated.对于无头服务,不分配集群 IP。

For headless Services that define selectors, the endpoints controller creates Endpoints records in the API, and modifies the DNS configuration to return records (addresses) that point directly to the Pods backing the Service.对于定义选择器的无头服务,端点 controller 在 API 中创建端点记录,并修改 DNS 配置以返回直接指向该服务的记录(地址)。

This means that whenever you query the DNS name for your Service (ie my-svc.my-namespace.svc.cluster-domain.example), what you get is a list of all the Pod IPs (unlike regular services where you get the cluster IP).这意味着,每当您查询服务的 DNS 名称时(即 my-svc.my-namespace.svc.cluster-domain.example),您得到的是所有 Pod IP 的列表(与获得集群 IP)。 You can then select your Pods using your own mechanisms.然后,您可以使用自己的机制 select 您的 Pod。

Regarding your new question, if that is your only issue, you can use session affinity.关于您的新问题,如果这是您唯一的问题,您可以使用 session 亲和力。 If you set service.spec.sessionAffinity to ClientIP , then connections from a particular client will always go to the same Pod each time.如果您将service.spec.sessionAffinity设置为ClientIP ,那么来自特定客户端的连接每次将始终 go 到同一个 Pod。 You don't need other modifications like the headless Services mentioned above.您不需要像上面提到的无头服务那样进行其他修改。

IMO, the only way to achieve this will be: IMO,实现这一目标的唯一方法是:

  1. Instead of using a deployment with 3 replicas, use 3 deployments with 1 replicas each (or just create pods only);不要使用具有 3 个副本的部署,而是使用每个具有 1 个副本的 3 个部署(或仅创建 pod); deployment1 -> pod1, deployment2 -> pod2, deployment3 -> pod3部署1-> pod1,部署2-> pod2,部署3-> pod3
  2. Expose all the deployments on a separate service, service1 -> deployment1, service2 -> deployment2, service3 -> deployment3将所有部署暴露在一个单独的服务上,service1 -> deployment1, service2 -> deployment2, service3 -> deployment3
  3. Create an ingress resource and route to each pod using the service for each deployment.为每个部署使用服务创建入口资源并路由到每个 pod。 For example:例如:
    • ingress-url/service1入口网址/服务1
    • ingress-url/service2入口网址/服务2
    • ingress-url/service3入口网址/服务3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM