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.
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.
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.
You can use Daemonsets
in combination with nodeSelector
or affinity
. Alternatively you could configure podAntiAffinity
on your Pod
s, 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
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