问题
I am running Kubernetes on "Docker Desktop" in Windows.
I have a LoadBalancer Service for a deployment which has 3 replicas. I would like to access SPECIFIC pod through some means (such as via URL path : < serviceIP >:8090/pod1).
Is there any way to achieve this usecase?
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
My end goal is to achieve horizontal auto-scaling of pods.
How Application designed/and works as of now (without kubernetes) :
There are 3 components : REST-Server, Stream-Server (3 instances locally on different JVM on different ports), and 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.
回答1:
You can use StatefulSets if you are not required to use deployment.
For replica 3, you will have 3 pods named
- stream-deployment-0
- stream-deployment-1
- stream-deployment-2
You can access each pod as $(podname).$(service name).$(namespace).svc.cluster.local
For details, check this
You may also want to set up an ingress to point each pod from outside of the cluster.
回答2:
As mentioned by aerokite, you can use StatefulSets. However, if you don't want to modify your deployments, you can simply use Headless Services. As specified in the documentation:
For headless Services, a cluster IP is not allocated.
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.
This means that whenever you query the DNS name for your Service (i.e. 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). You can then select your Pods using your own mechanisms.
Regarding your new question, if that is your only issue, you can use session affinity. If you set service.spec.sessionAffinity
to ClientIP
, then connections from a particular client will always go to the same Pod each time. You don't need other modifications like the headless Services mentioned above.
回答3:
IMO, the only way to achieve this will be:
- Instead of using a deployment with 3 replicas, use 3 deployments with 1 replicas each (or just create pods only); deployment1 -> pod1, deployment2 -> pod2, deployment3 -> pod3
- Expose all the deployments on a separate service, service1 -> deployment1, service2 -> deployment2, service3 -> deployment3
- Create an ingress resource and route to each pod using the service for each deployment. For example:
- ingress-url/service1
- ingress-url/service2
- ingress-url/service3
来源:https://stackoverflow.com/questions/58007073/how-to-route-to-specific-pod-through-kubernetes-service-like-a-gateway-api