Is it possible to assign a pod of StatefulSet to a specific node of a Kubernetes cluster? Is it possible to assign a pod of StatefulSet to a specific node of a Kubernetes cluster? kubernetes kubernetes

Is it possible to assign a pod of StatefulSet to a specific node of a Kubernetes cluster?


You can delegate responsibility for scheduling arbitrary subsets of pods to your own custom scheduler(s) that run(s) alongside, or instead of, the default Kubernetes scheduler.

You can write your own custom scheduler. A custom scheduler can be written in any language and can be as simple or complex as you need. Below is a very simple example of a custom scheduler written in Bash that assigns a node randomly. Note that you need to run this along with kubectl proxy for it to work.

SERVER='localhost:8001'while true;do    for PODNAME in $(kubectl --server $SERVER get pods -o json | jq '.items[] | select(.spec.schedulerName == "my-scheduler") | select(.spec.nodeName == null) | .metadata.name' | tr -d '"');    do        NODES=($(kubectl --server $SERVER get nodes -o json | jq '.items[].metadata.name' | tr -d '"'))        NUMNODES=${#NODES[@]}        CHOSEN=${NODES[$[$RANDOM % $NUMNODES]]}        curl --header "Content-Type:application/json" --request POST --data '{"apiVersion":"v1", "kind": "Binding", "metadata": {"name": "'$PODNAME'"}, "target": {"apiVersion": "v1", "kind": "Node", "name": "'$CHOSEN'"}}' http://$SERVER/api/v1/namespaces/default/pods/$PODNAME/binding/        echo "Assigned $PODNAME to $CHOSEN"    done    sleep 1done

Then just in your StatefulSet configuration file under specification section you will have to add schedulerName: your-scheduler line.

You can also use pod affinity:.

Example:

apiVersion: apps/v1kind: StatefulSetmetadata:  name: redis-cachespec:  selector:    matchLabels:      app: store  replicas: 3  template:    metadata:      labels:        app: store    spec:      affinity:        podAntiAffinity:          requiredDuringSchedulingIgnoredDuringExecution:          - labelSelector:              matchExpressions:              - key: app                operator: In                values:                - store            topologyKey: "kubernetes.io/hostname"      containers:      - name: redis-server        image: redis:3.2-alpine

The below yaml snippet of the webserver statefuset has podAntiAffinity and podAffinity configured. This informs the scheduler that all its replicas are to be co-located with pods that have selector label app=store. This will also ensure that each web-server replica does not co-locate on a single node.

apiVersion: apps/v1kind: StatefulSetmetadata:  name: web-serverspec:  selector:    matchLabels:      app: web-store  replicas: 3  template:    metadata:      labels:        app: web-store    spec:      affinity:        podAntiAffinity:          requiredDuringSchedulingIgnoredDuringExecution:          - labelSelector:              matchExpressions:              - key: app                operator: In                values:                - web-store            topologyKey: "kubernetes.io/hostname"        podAffinity:          requiredDuringSchedulingIgnoredDuringExecution:          - labelSelector:              matchExpressions:              - key: app                operator: In                values:                - store            topologyKey: "kubernetes.io/hostname"      containers:      - name: web-app        image: nginx:1.12-alpine

If we create the above two deployments, our three node cluster should look like below.

node-1              node-2           node-3webserver-1     webserver-2          webserver-3cache-1             cache-2          cache-3

The above example uses PodAntiAffinity rule with topologyKey: "kubernetes.io/hostname" to deploy the redis cluster so that no two instances are located on the same host

You can simply define three replicas of specific pod and define particular pod configuration file, egg.:There is label: nodeName which is the simplest form of node selection constraint, but due to its limitations it is typically not used. nodeName is a field of PodSpec. If it is non-empty, the scheduler ignores the pod and the kubelet running on the named node tries to run the pod. Thus, if nodeName is provided in the PodSpec, it takes precedence over the above methods for node selection.

Here is an example of a pod config file using the nodeName field:

apiVersion: v1kind: Podmetadata:  name: nginxspec:  containers:  - name: nginx    image: nginx  nodeName: kube-worker-1

More information about scheduler: custom-scheduler.

Take a look on this article: assigining-pods-kubernetes.


You can do this using nodeSelector and node affinity (take a look at this guide https://kubernetes.io/docs/concepts/configuration/assign-pod-node/), anyone can be used to run pods on specific nodes. But if the node has taints (restrictions) then you need to add tolerations for those nodes (more can be found here https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/). Using this approach, you can specify a list of nodes to be used for your pod's scheduling, the catch is if you specify for ex. 3 nodes and you have 5 pods then you don't have control how many pods will run on each of these nodes. They gets distributed as per kube-schedular. Another relevant use case: If you want to run one pod in each of the specified nodes, you can create a daemonset and select nodes using nodeSelector.


take a look to this guideline https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/ however, what you are looking for is the nodeSelector directive that should be placed in the pod spec.