I was looking for method to upgrade k8s version without downtime for Azure AKS and found this amazing blog post
Add a new Node pool. Now the version of new node pool is higher(same with control plane). Then add a label to it, e.g. nodePool=newNodePool.
Patch all application to the new node pool. (By nodeSelector)
$ kubectl get deployment -n {namespace} -o name | xargs kubectl patch -p "{\"spec\":{\"template\":{\"spec\":{\"nodeSelector\":{\"nodePool\":\"newNodePool\"}}}}}" -n {namespace}
Check the pods if are scheduled to the new node pool.
$ kubectl get pods -owide
Delete the old node pool.