Let’s deploy our workload, in our examples we will a deploy simple nginx Pod just to simulate the behaviour of Ocean alongside the Kubernetes Scheduler.
Create a file vng-example.yaml
with the following content
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-1
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-dev
image: nginx
resources:
requests:
memory: "100Mi"
cpu: "256m"
nodeSelector:
env: ocean-workshop
example: "1"
Apply the file using kubectl, run kubectl apply -f vng-example.yaml
➜ kubectl apply -f vng-example.yaml
deployment.apps/example-1 created
List the pods,nodes from the cluster, you’ll be able to see the created Pod in a Pending state, run kubectl get pods,nodes
➜ kubectl get pods,nodes
NAME READY STATUS RESTARTS AGE
pod/example-1-7f8b5549bb-4k8rp 0/1 Pending 0 14s
NAME STATUS ROLES AGE VERSION
aks-agentpool-46800815-vmss000000 Ready <none> 64d v1.24.15
Following a couple of minutes, run kubectl get pods,nodes -o wide
, we will see that a new node joined our cluster and that the Pod is being created/running on top of it
➜ kubectl get pods,nodes -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/example-1-7f8b5549bb-4k8rp 0/1 ContainerCreating 0 83s <none> aks-agentpool-46800815-vmss000000 <none> <none>
NAME STATUS ROLES AGE VERSION INTERNAL-IP
aks-agentpool-46800815-vmss000000 Ready agent 64d v1.24.15 10.224.0.4
EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
<none> Ubuntu 18.04.6 LTS 5.4.0-1112-azure containerd://1.7.1+azure-1
Describe the node to verify the nodeLabels are assigned to it, run kubectl describe <node-name>
➜ kubectl describe node aks-agentpool-46800815-vmss000000
Name: aks-agentpool-46800815-vmss000000
Roles: agent
Labels: agentpool=agentpool
beta.kubernetes.io/arch=amd64
beta.kubernetes.io/instance-type=Standard_DS2_v2
beta.kubernetes.io/os=linux
failure-domain.beta.kubernetes.io/region=eastus
failure-domain.beta.kubernetes.io/zone=eastus-1
kubernetes.azure.com/agentpool=agentpool
kubernetes.azure.com/cluster=MC_yaros-rbac-test_yar-private-preview_eastus
kubernetes.azure.com/consolidated-additional-properties=3ad9cafe-3324-11ee-a619-16bb608ba0be
kubernetes.azure.com/kubelet-identity-client-id=c82dc65e-5484-4309-8da6-efd14c60d472
kubernetes.azure.com/mode=system
kubernetes.azure.com/node-image-version=AKSUbuntu-1804gen2containerd-202307.27.0
kubernetes.azure.com/nodepool-type=VirtualMachineScaleSets
kubernetes.azure.com/os-sku=Ubuntu
kubernetes.azure.com/role=agent
kubernetes.azure.com/storageprofile=managed
kubernetes.azure.com/storagetier=Premium_LRS
kubernetes.io/arch=amd64
kubernetes.io/hostname=aks-agentpool-46800815-vmss000000
kubernetes.io/os=linux
kubernetes.io/role=agent
node-role.kubernetes.io/agent=
node.kubernetes.io/instance-type=Standard_DS2_v2
storageprofile=managed
storagetier=Premium_LRS
topology.disk.csi.azure.com/zone=eastus-1
topology.kubernetes.io/region=eastus
topology.kubernetes.io/zone=eastus-1
env=ocean-workshop
example=1
In addition to node labels you define, nodes come with pre-populated standard set of labels. You can review kubernetes Well-Known Labels, Annotations and Taints and Azure Reserved system labels.
Ocean expands the built in Kubernetes node-labels functionality with some proprietary labels supported by Ocean. See Labels & Taints for further details.
We are now able to specify when we want to force a specific workload to run on machines of the example-1
VNG, in the current state, Pods with no specific constraints (e.g not directed toward specific type of nodes) might be placed on nodes from the example-1
VNG, in order to prevent that we will also need to assign a Taint to the VNG, the Pods that we want to run on the tainted VNG should Tolerate that Taint.
In order to demonstrate that, let’s add a new VNG, follow the same process but specify the following configurations - in the Name specify example-2
, in the Node Selection section specify:
Node Labels (formatted as key: value)
Node Taints
Click the save button on the bottom of the page
Create a file vng-example-2.yaml
file with the following content:
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-2-1
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-dev
image: nginx
resources:
requests:
memory: "100Mi"
cpu: "256m"
nodeSelector:
env: ocean-workshop
example: "2"
tolerations:
- key: "example"
operator: "Equal"
value: "2"
effect: "NoSchedule"
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-2-2
spec:
selector:
matchLabels:
app: nginx
replicas: 1
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-dev
image: nginx
resources:
requests:
memory: "100Mi"
cpu: "256m"
nodeSelector:
env: ocean-workshop
example: "2"
While both Pods require our nodeLabels only one of them tolerates the node taints, let’s view it’s effect:
Run kubectl apply -f vng-example-2.yaml
➜ kubectl apply -f vng-example-2.yaml
deployment.apps/example-2-1 created
deployment.apps/example-2-2 created
We will now see that both our Pods are pending, run kubectl get pods,nodes
➜ kubectl get pods,nodes
NAME READY STATUS RESTARTS AGE
example-1-7f8b5549bb-xnsfq 1/1 Running 0 48m
example-2-1-64d9d4877d-rv2pg 0/1 Pending 0 39s
example-2-2-7d55b5b8cf-dfkpw 0/1 Pending 0 37s
NAME STATUS ROLES AGE VERSION
aks-agentpool-46800815-vmss000000 Ready <none> 64d v1.24.15
A couple of minutes later Ocean will scale up a new machine to satisfy the supported Pod, we will see that only one of the Pods (example-2-1
) will be scheduled while the other wont since it does not tolerate the nodes taint.
Run kubectl get pods,nodes -o wide
➜ kubectl get pods,nodes -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
example-1-7f8b5549bb-xnsfq 1/1 Running 0 50m 192.168.48.21 aks-agentpool-46800815-vmss000000 <none> <none>
example-2-1-64d9d4877d-rv2pg 1/1 Running 0 2m26s 192.168.24.234 aks-agentpool-46800815-vmss000000 <none> <none>
example-2-2-7d55b5b8cf-dfkpw 0/1 Pending 0 2m24s <none> <none> <none> <none>
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
aks-agentpool-46805500-vmss000005 Ready <none> 87s v1.24.15 192.168.24.193 54.149.39.228 Ubuntu 18.04.6 LTS 5.4.0-1112-azure containerd://1.7.1+azure-1
aks-agentpool-46800815-vmss000000 Ready <none> 64d v1.24.15 192.168.46.105 35.160.241.120 Ubuntu 18.04.6 LTS 5.4.0-1112-azure containerd://1.7.1+azure-1
Run kubectl describe <pod-name>
Under the Events section you’ll see that the reason for the Pod not being scheduled is because there is a node with a taint that the pod did not tolerate
➜ kubectl describe pod/example-2-2-7d55b5b8cf-dfkpw
Name: example-2-2-7d55b5b8cf-dfkpw
Namespace: default
Priority: 0
Service Account: default
Node: <none>
Labels: app=nginx
pod-template-hash=df4d44b8c
Annotations: <none>
Status: Pending
IP:
IPs: <none>
Controlled By: ReplicaSet/example-2-2-7d55b5b8cf
Containers:
nginx-dev:
Image: nginx
Port: <none>
Host Port: <none>
Requests:
cpu: 256m
memory: 100Mi
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-5dqmd (ro)
Conditions:
Type Status
PodScheduled False
Volumes:
kube-api-access-5dqmd:
Type: Projected (a volume that contains injected data from multiple sources)
TokenExpirationSeconds: 3607
ConfigMapName: kube-root-ca.crt
ConfigMapOptional: <nil>
DownwardAPI: true
QoS Class: Burstable
Node-Selectors: env=ocean-workshop
example=2
Tolerations: example=2:NoSchedule
node.kubernetes.io/memory-pressure:NoSchedule op=Exists
node.kubernetes.io/not-ready:NoExecute op=Exists for 300s
node.kubernetes.io/unreachable:NoExecute op=Exists for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 39s default-scheduler 0/1 nodes are available: 1 node(s) didn't match Pod's node affinity/selector. preemption: 0/1 nodes are available: 1 Preemption is not helpful for scheduling.