Load balancing to multiple containers of same app in a pod

7/21/2019

I have a scenario where I need to have two instances of an app container run within the same pod. I have them setup to listen on different ports. Below is how the Deployment manifest looks like. The Pod launches just fine with the expected number of containers. I can even connect to both ports on the podIP from other pods.

kind: Deployment
metadata:
  labels:
    service: app1-service
  name: app1-dep
  namespace: exp
spec:
  template:
    spec:
      contianers:
        - image: app1:1.20
          name: app1
          ports:
          - containerPort: 9000
            protocol: TCP
        - image: app1:1.20
          name: app1-s1
          ports:
          - containerPort: 9001
            protocol: TCP

I can even create two different Services one for each port of the container, and that works great as well. I can individually reach both Services and end up on the respective container within the Pod.

apiVersion: v1
kind: Service
metadata:
  name: app1
  namespace: exp
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 9000
  selector:
    service: app1-service
  sessionAffinity: None
  type: ClusterIP

---
apiVersion: v1
kind: Service
metadata:
  name: app1-s1
  namespace: exp
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 9001
  selector:
    service: app1-service
  sessionAffinity: None
  type: ClusterIP

I want both the instances of the container behind a single service, that round robins between both the containers. How can I achieve that? Is it possible within the realm of services? Or would I need to explore ingress for something like this?

-- Naga
kubernetes
kubernetes-service

3 Answers

7/21/2019

What I would do is to separate the app in two different deployments, with one container in each deployment. I would set the same labels to both deployments and attack them both with one single service.

This way, you don't even have to run them on different ports.

Later on, if you would want one of them to receive more traffic, I would just play with the number of the replicas of each deployment.

-- suren
Source: StackOverflow

7/21/2019

One can expose multiple ports using a single service. In Kubernetes-service manifest, spec.ports[] is an array. So, one can specify multiple ports in it. For example, see bellow:

apiVersion: v1
kind: Service
metadata:
  name: app1
  namespace: exp
spec:
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: 9000
  - name: http-s1
    port: 81
    protocol: TCP
    targetPort: 9001
  selector:
    service: app1-service
  sessionAffinity: None
  type: ClusterIP

Now, the hostname is same except the port and by default, kube-proxy in userspace mode chooses a backend via a round-robin algorithm.

-- Shudipta Sharma
Source: StackOverflow

7/21/2019

Kubernetes services has three proxy modes: iptables (is the default), userspace, IPVS.

  • Userspace: is the older way and it distribute in round-robin as the only way.
  • Iptables: is the default and select at random one pod and stick with it.
  • IPVS: Has multiple ways to distribute traffic but first you have to install it on your node, for example on centos node with this command: yum install ipvsadm and then make it available.

Like i said, Kubernetes service by default has no round-robin. To activate IPVS you have to add a parameter to kube-proxy

--proxy-mode=ipvs

--ipvs-scheduler=rr (to select round robin)

-- EAT
Source: StackOverflow