In a vSphere Supervisor Workload Cluster, a pod is stuck ContainerCreating or Init state.
Note: This KB article is written from the perspective of using vSAN File Shares in a vSphere Supervisor environment.
While connected to the affected Workload Cluster context, one or more of the following symptoms are observed:
kubectl get pods -n <pod namespace> -o wide
NAMESPACE NAME READY STATUS
<pod namespace> <pod name-a> <container/count> Init:0/1
<pod namespace> <pod name-b> <container/count> ContainerCreating
kubectl describe pod -n <pod namespace> <pod name>
Events:
Type Reason Age From Message
---- ------ ---- ------- ------------
Warning FailedMount ##s kubelet MountVolume.SetUp failed for volume "<pv name>" : rpc error: code = Internal desc = error publish volume to target path: mount failed: exit status 32
mounting arguments: -t nfs4 -o hard,sec=sys,vers=#,minorversion=# <fileshare path> /var/lib/kubelet/pods/<id>/volumes/kubernetes.io~csi/<pv name>/mount
output: mount.nfs4: mounting <fileshare path> failed, reason given by server: No such file or directory
kubectl get pods -n vmware-system-csi
While connected to the Supervisor cluster context, the following symptoms are present:
When viewing the affected vSAN File Share(s) in the vSphere web UI, Net Access Control shows the following message:
Net access control No one can access the file share object.
vSphere with Tanzu 7.0
vSphere with Tanzu 8.0
This issue is caused by stale CNS resources for volumes and fileshares.
Stale CNS resources can be caused by manual deletion of nodes without allowing the system to properly drain pods or detach volumes from the deleting node and update the CNS resources accordingly.
In some cases, the volume may remain attached to another node due to missing ACLs in Net Access Control (“No one can access the file share object”), preventing the system from detaching it properly.
IMPORTANT: It is not an appropriate troubleshooting practice to manually delete nodes.
System-initiated deletions such as through a rolling redeployment or upgrade will perform a drain on the deleting node and detach volumes from the node.
However, if the node is manually deleted before the system completes draining and detaching volumes from the deleted node, this will result in stale resources such as the ones that will be advised regarding in this KB.
Rolling redeployments and upgrades will create a new node with the desired changes/version first and await health checks before moving onto deletion of an older node.
A common cause of nodes stuck deleting is due to Pod Disruption Budgets (PDBs):
A common cause of nodes failing to create is due to third party webhooks or unhealthy control plane nodes in the affected workload cluster:
The corresponding stale CNS resources will need to be manually corrected to reflect the current state of the environment.
kubectl get pod -o wide -n <pod namespace>
kubectl describe pod -n <pod namespace> <pod name>
mounting arguments: -t nfs4 -o hard,sec=sys,vers=#,minorversion=# <fileshare path> /var/lib/kubelet/pods/<id>/volumes/kubernetes.io~csi/<pv name>/mount
kubectl describe pod -n <pod namespace> <pod name>
Volumes:
<volume-type-a>:
Type: PersistentVolumeClaim
ClaimName: <name of pvc-a>
<volume-type-b>:
Type: PersistentVolumeClaim
ClaimName: <name of pvc-b>
You can perform either a ping or a curl -vk to the noted File Share instance in the problematic pod's error message.
kubectl get pod -A -o yaml | grep <name of pvc from step 2>
kubectl get pv | grep <pvc name from step 2>
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS
<pv name> # <RWO/RWX> <Retain/Recycle/Delete> <Bound/Pending> <pvc name from Step 2> <storageclass>
kubectl get volumeattachment -o wide | grep <pv name from previous step>
NAME ATTACHER PV NODE ATTACHED AGE
<volume attachment name> csi.vsphere.vmware.com <pv name> <node name> <True/False> <age>
kubectl get nodes
If there are two volumeattachments associated with two different existing nodes for one PV:
Pods can be managed by different kubernetes objects depending on initial deployment factors. For example, pods can be deployed by: deployments, replicasets, daemonsets, statefulsets or jobs.
kubectl get <kubernetes object> -n <pod namespace>
kubectl scale deployment -n <deployment namespace> <deployment name> --replicas=0
kubectl get volumeattachment -A | grep <pv name>
kubectl delete volumeattachment <volumeattachment/previous node> -n <namespace>
If there is an associated cnsfileaccessfileconfig or cnsfilevolumeclient, please see the CNSFile Checks section below
kubectl get volumeattachment -o wide | grep <pv name>
kubectl get pod -n <pod namespace> -o wide
kubectl describe pod -n <pod namespace> <pod name>
Otherwise:
Pods can be managed by different kubernetes objects depending on initial deployment factors. For example, pods can be deployed by: deployments, replicasets, daemonsets, statefulsets or jobs.
kubectl get <kubernetes object> -n <pod namespace>
kubectl scale deployment -n <deployment namespace> <deployment name> --replicas=0
kubectl get pod -n <pod namespace>
kubectl get volumeattachment -A | grep <pv name>
kubectl get cnsfileaccessconfig,cnsfilevolumeclient -n <workload cluster namespace> | grep <pv name>
If there is an associated cnsfileaccessfileconfig or cnsfilevolumeclient, please see the CNSFile Checks section below
kubectl get volumeattachment -o wide | grep <pv name>
kubectl get pod -n <pod namespace> -o wide
kubectl describe pod -n <pod namespace> <pod name>
Each cnsfileaccessconfig is named for the workload cluster node and the persistent volume that it is associated with. Describing this object provides details on:
Each cnsfilevolumeclient is named for the file and persistent volume that it is associated with. Describing this object shows details on:
kubectl get cnsfileaccessconfig -n <workload cluster context> | grep <pv name>
kubectl describe cnsfileaccessconfig -n <workload cluster context> <cnsfileaccessconfig name>
error: 'Failed to get virtualmachine instance for VM with name: "<missing workload cluster node name>".
Error: virtualmachines.vmoperator.vmware.com "<missing workload cluster node name>" not found'
kubectl get vm,machine,vspheremachine -A | grep <missing workload cluster node name>
kubectl describe cnsfileaccessconfig -n <workload cluster namespace> <cnsfileaccessconfig name> | head
Metadata:
DeletionTimestamp: YYYY-MM-DD:HH:MM:SSZ
kubectl edit cnsfileaccessconfig -n <workload cluster context> <cnsfileaccessconfig name>
Finalizers:
- cns.vmware.com
kubectl get cnsfileaccessconfig -n <workload cluster namespace> <cnsfileaccessconfig name>
kubectl delete cnsfileaccessconfig -n <workload cluster namespace> <cnsfileaccessconfig name>
kubectl get cnsfileaccessconfig -n <workload cluster namespace> <cnsaccessfileconfig name>
kubectl get cnsfilevolumeclient -n <workload cluster namespace> -o yaml | grep <affected pv name>
kubectl get vm,machine,vspheremachine -A | grep <node name>
kubectl edit cnsfilevolumeclient -n <workload cluster namespace> <cnsfilevolumeclient name>
spec:
externalIPtoClientVMs:
<IP address>:
- <missing workload cluster node name>
- <existing workload cluster node name>
kubectl get volumeattachments -o wide | grep <pv name>
kubectl delete volumeattachment <volumeattachment name>
kubectl get volumeattachments -o wide | grep <pv name>
kubectl get pod -n <pod namespace>