Colocate pods in Kubernetes

11/23/2019
  • I have a kubernetes cluster which is spread across 2 zones- zone1 and zone2.

  • I have 2 applications- a web application and a database. The web application's configurations are stored in the database. Both the application as well as the database are deployed as stateful applications.

  • The idea is to deploy 2 replica sets for web application (application-0 and application-1) and 2 replica for database (database-0 and database-1). application-0 points to database-0, application-1 points to database-1.

  • Pod anti-affinity has been enabled. So preferably application-0 and application-1 will not be in same zone. Also database-0 and database-1 will not be in same zone.

  • I want to ensure application-0 and database-0 are in the same zone. And application-1 and database-1 are in another zone. So that the performance of the web application is not compromised. Is that possible?

-- Rana
affinity
kubernetes
performance
pod

3 Answers

11/23/2019

PodAntiAffinity to spread to Zones

For your database

metadata:
  labels:
    app: db
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - db
        topologyKey: "kubernetes.io/hostname"

For your web-app

metadata:
  labels:
    app: web-app
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - web-app
        topologyKey: "kubernetes.io/hostname"

PodAffinity to co-locate pods on nodes

In addition, you add podAffinity to your web-app (not database) to co-locate it on nodes with your database.

With podAffinity added for your web-app:

metadata:
  labels:
    app: web-app
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - web-app
        topologyKey: "kubernetes.io/hostname"
    podAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector:
          matchExpressions:
          - key: app
            operator: In
            values:
            - db
        topologyKey: "kubernetes.io/hostname"

Result

With both PodAntiAffinity and PodAffinity you will get web-app-X co-located with db-X.

web-app-1     web-app-2
db-1          db-2

See the Kubernetes documentation has an example to co-locate cache with app on nodes about PodAffinity and ´PodAntiAffinity`.

Stable Network identity for StatefulSet

To address one specific instance of a StatefulSet, create an Headless Service with ClusterIP: None for each db replica. This allow your web-apps to connect to a specific instance.

Access the closest db instance

Now your web-apps can connect to db-0 and db-1 via the headless services. Let your web-apps connect to both initially, and use the one with shortest response time - that one is most likely the one on the same node.

-- Jonas
Source: StackOverflow

11/23/2019

Just like you used anti-affinity rules to avoid provisioning both apps in the same zone, you can use affinity to provision app-0 only in the zone where db-0 exists, technically that would mean that you could drop anti affinity from app completely as if you tell it to schedule only in the zone of db, and db is defined to spread zones with anti-affinity, you inherit the distribution from the database part.

-- Radek 'Goblin' Pieczonka
Source: StackOverflow

11/23/2019

If you want to have strict separation of the workloads over the two zones - I'd suggest using nodeSelector on a node's zone.

A similar result is possible with pod affinity but it's more complex and to get the clear split you describe. You'd need to use the requiredDuringScheduling / execution rules which are usually best avoided unless you really need them.

-- Charlie Egan
Source: StackOverflow