VMware guest customization can write /etc/netplan/99-netcfg-vmware.yaml. If the template already has another active netplan file, the host can end up with multiple network authorities.
That can break routing, DNS, bootstrap scripts, Kubernetes node communication, and storage initialization.
Symptoms
Common signs:
Error: Conflicting default route declarations for IPv4
first declared in nic0 but also in ens192
or:
Destination Host Unreachable
or DNS search drift like:
resolv_conf_search = .
netplan_search = []
Inspect Netplan Ownership
ls -l /etc/netplan
sudo grep -R "routes:\|gateway\|search:" /etc/netplan -n
If both a template file and VMware file are present, decide which one owns networking.
Example conflict:
/etc/netplan/01-template-static.yaml
/etc/netplan/99-netcfg-vmware.yaml
Verify Active Routing
ip -br addr
ip route
networkctl status ens192 --no-pager
If the default route is missing, test the expected route manually:
sudo ip route replace default via 192.0.2.1 dev ens192
ping -c 3 192.0.2.1
If ARP fails, compare the vSphere port group against a working VM:
govc device.ls -vm /DC-Site-A/vm/K8s-Cluster/NonProd/cluster-a-worker-01
govc device.ls -vm /DC-Site-A/vm/K8s-Cluster/NonProd/cluster-a-worker-02
Normalize To One Netplan File
If VMware customization is the current network authority, keep only the VMware-generated file:
if [ -f /etc/netplan/99-netcfg-vmware.yaml ]; then
for f in /etc/netplan/*.yaml /etc/netplan/*.yml; do
[ -f "$f" ] || continue
case "$f" in
/etc/netplan/99-netcfg-vmware.yaml)
echo "keeping $f"
;;
*)
echo "removing $f"
rm -f "$f"
;;
esac
done
fi
Then validate and apply:
sudo netplan generate
sudo netplan apply
ip route
resolvectl status
Important Shell Detail
If this is run through Ansible shell, remember that /bin/sh may execute the script. Bash-only syntax such as [[ ... ]] can fail:
/bin/sh: 47: [[: not found
Use POSIX [ ... ] syntax or explicitly run the script with Bash.
Operating Model
Pick one owner:
- VMware customization owns primary NIC, hostname, gateway, and DNS.
- Bootstrap owns additional storage NICs and iSCSI-specific netplan.
- Cloud-init userdata runs bootstrap and avoids competing with network ownership.
The failure pattern is usually not one bad command. It is multiple systems trying to own the same network configuration.
If VMware customization owns DNS, make sure Terraform separates the VM identity domain from resolver search suffixes. See Terraform vSphere DNS Search Suffix Ownership.