How to ensure only one pod runs on my node in GKE?

3/8/2019

In my application, I have a rest server which locally interacts with a database via the command line (it's a long story). Anyway, the database is mounted in a local ssd on the node. I can guarantee that only pods of that type will by scheduled in the node pool, as I have tainted the nodes and added tolerances to my pods.

What I want to know is, how can I prevent kubernetes from scheduling multiple instances of my pod on a single node? I want to avoid this as I want my pod to be able to consume as much CPU as possible, and I also don't want multiple pods to interact via the local ssd.

How do I prevent scheduling of more than one pod of my type onto the node? I was thinking daemon sets at first, but I think down the line, I want to set my node pool to auto scale, that way when I have n nodes in my pool, and I request n+1 replicas, the node pool automatically scales up.

-- Andy
google-kubernetes-engine
kubernetes

3 Answers

3/8/2019

I can suggest two ways of going about this. One is to restrict the number of pods schedulable on a node, and the other is to assign the pod to a given node while requesting for the entirety of the resources available in the node.

1. Restricting number of schedulable pods per node

You can set this restriction when you're creating a new cluster, however it is limiting if later you change your mind. Find the following field in the advanced settings as you create the cluster.

enter image description here

2. Assigning pod to specific node and occupying all resources

Another option is to set the resource request numbers such that they match a node's resources, and assign it to a given node, using the nodeSelector and labels.

Check out this link for how to assign pods to a specific node.

-- cookiedough
Source: StackOverflow

3/9/2019

You can use Daemonsets in combination with nodeSelector or affinity. Alternatively you could configure podAntiAffinity on your Pods, for example:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: rest-server
spec:
  selector:
    matchLabels:
      app: rest-server
  replicas: 3
  template:
    metadata:
      labels:
        app: rest-server
    spec:
      affinity:
        podAntiAffinity:
          requiredDuringSchedulingIgnoredDuringExecution:
          - labelSelector:
              matchExpressions:
              - key: app
                operator: In
                values:
                - rest-server
            topologyKey: "kubernetes.io/hostname"
      containers:
      - name: rest-server
        image: nginx:1.12-alpine
-- webwurst
Source: StackOverflow

3/15/2019

Depending on what you are trying to achieve, DaemonSets might not be a complete answer, because DaemonSet is NOT auto scaled, and it will only place a pod in a new node; when you add new nodes to your pool.

If you are looking to modify your workload with n+1 replicas,it’s better to use podAntiAffinity, controlling scheduling with node taints and cluster autoscaler; this will guarantee that a new node will be added when you increase your pods and deleted when you scale down your pods:

apiVersion: v1
kind: ReplicationController
metadata:
 name: echoheaders
spec:
 replicas: 1
 template:
   metadata:
     labels:
       app: echoheaders
   spec:
     affinity:
       podAntiAffinity:
         requiredDuringSchedulingIgnoredDuringExecution:
         - labelSelector:
             matchExpressions:
             - key: app
               operator: In
               values:
               - echoheaders
           topologyKey: "kubernetes.io/hostname"
     containers:
     - name: echoheaders
       image: k8s.gcr.io/echoserver:1.4
       ports:
       - containerPort: 8080
     tolerations:
     - key: dedicated
       operator: Equal
       value: experimental
       effect: NoSchedule
-- Ahmad Parsaei
Source: StackOverflow