kubeadm already allows to set taints for the joining node using the configuration file at join time.
Steps on how to do this at node join time are as below
Construct a Config.yaml file with taint details and bootstrap details as recived from master at kubeadm init time.
Example config.yaml you should update values as per your cluster info on below
apiVersion: kubeadm.k8s.io/v1beta1
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: "<control_plain_ip>:6443"
token: "your_token"
caCertHashes:
- sha256:$CERT_HASH
nodeRegistration:
taints:
- effect: NoSchedule
key: specialnode1.kubernetes.io/SpecialNode1
Pass this config from node you want to join it will join with a taint set at startup.
root@k8s-node01:# kubeadm join --config=config.yaml
[kubelet-start] Starting the kubelet
[kubelet-start] Waiting for the kubelet to perform the TLS Bootstrap...
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
Node should join the cluster and will have a taint at startup time so pods not having tolerance will not be scheduled on this new node.
ubuntu@k8s-master:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 18m v1.17.2
k8s-node01 Ready <none> 8m11s v1.17.2
Verify the taint as below
$ kubectl describe node k8s-node01 | grep -i Taint
Taints: specialnode1.kubernetes.io/SpecialNode1:NoSchedule
To further test this we will create a daemon set which will run on node01 and add another node02 with new taint , daemon set should not autoscale to new node with new taint.
ubuntu@k8s-master:~$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 24m v1.17.2
k8s-node01 Ready <none> 14m v1.17.2
ubuntu@k8s-master:~$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-npmz5 1/1 Running 0 50s 192.168.85.193 k8s-node01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24m <none>
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset.apps/nginx 1 1 1 1 1 <none> 50s nginx nginx app=nginx
Add new Node with new config.yaml and verify the node is ready and taint is set on new node added to cluster
apiVersion: kubeadm.k8s.io/v1beta1
kind: JoinConfiguration
discovery:
bootstrapToken:
apiServerEndpoint: "<control_plain_ip>:6443"
token: "your_token"
caCertHashes:
- sha256:$CERT_HASH
nodeRegistration:
taints:
- effect: NoSchedule
key: specialnode2.kubernetes.io/SpecialNode2
$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8s-master Ready master 25m v1.17.2
k8s-node01 Ready <none> 15m v1.17.2
k8s-node02 Ready <none> 22s v1.17.2
Note the new taint on node02
$ kubectl describe node k8s-node02 | grep -i Taint
Taints: specialnode2.kubernetes.io/SpecialNode2:NoSchedule
Now check if daemon set has scaled to new node or not, it will not unless we remove the taint or add tolerance to daemonset
$ kubectl get all -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/nginx-npmz5 1/1 Running 0 3m46s 192.168.85.193 k8s-node01 <none> <none>
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 27m <none>
NAME DESIRED CURRENT READY UP-TO-DATE AVAILABLE NODE SELECTOR AGE CONTAINERS IMAGES SELECTOR
daemonset.apps/nginx 1 1 1 1 1 <none> 3m46s nginx nginx app=nginx
So we can use above steps to add a new node to a running cluster and choose what is scheduled on it using taints.