Change:
What keywords did you search in Kubernetes issues before filing this one?: VMware, vSphere, IP, UUID BUG REPORT. Kubernetes version: Environment: Cloud provider or hardware configuration: VMware vSphere 6.5.0 OS : Debian GNU/Linux 8.7 (jessie) Kernel : Install tools: Kargo What happened: Some containers were launched on a node with a name containing the hostname of a different node and the does not retrieve the right node name : Here is retrieved instead of . When using the VSphere Cloud provider, the node name is retrieved from the function in Since this PR (), the node data are retrieved based on the IP address instead of the UUID. The function gets all the IP address and check if one of the IP on any interface matches a VM on vSphere. The problem is that the docker0 interface has the same IP on all the nodes (usually 172.17.0.1) and this IP is referenced into VMware. As this IP may be the first to appear in the it will match the first VM that vSphere gives with the function and this can be any VM running Docker on vSphere. Thus, the provider has a big chance to not get the informations for the VM it is running on, leading to an inconsistent state in the cluster (wrong pod name for example). Anything else we need to know: An idea would be to first retrieve the VM name with the function and if no results use the IP address (and add an exclusion to not use the interface). What do you think ? If you think this might be the right way to do, we can try to propose the PR. Thanks for your feedback.
Wow, this very much is a bad, bad bug. It was introduced by one of my colleagues here at HPE. It's made worse if you run multiple Kubernetes clusters in the same vSphere Datacenter. I'll send a PR upstream tomorrow to resolve this. I think it's best to go back to using dmidecode, but maybe someone from VMware ( or ?) has another suggestion? This would still require root access, but I can't think of a better way to get the machine's ID.
Related issue Will dig in more. For now instead of making it a value determined runtime the deployment framework should have root privileges and can populate it as part of the cloud config post VM creation.
is my colleague. A little more info and a few ideas. I would also support going back to ` (still requires root though). We could also have the following logic: Get UUID and use it to get the VM Name with FindByUUID if possible, If not, get the hostname and use FindByDNSName, If still nothing is found, keep the current logic, excluding docker0 from the interfaces we examine. However, I agree with that getting this from the cloud config may be the best and most reliable solution.
I'm working on a patch right now that will do the following: Add a VMUUID field to the cloud config If VMUUID is not set, will use Error out if neither one is available
PR is - if someone would like to review :)

Discussion:
"errors" "fmt" "io" <del> "net" </del> <ins> "io/ioutil" </ins> "net/url" "path" "path/filepath"

WorkingDir string `gcfg:"working-dir"` // Soap round tripper count (retries = RoundTripper - 1) RoundTripperCount uint `gcfg:"soap-roundtrip-count"` <ins> // VMUUID is the VM Instance UUID of virtual machine which can be retrieved from instanceUuid // property in VmConfigInfo, or also set as vc.uuid in VMX file. // If not set, will be fetched from the machine via sysfs (requires root) VMUUID string `gcfg:"vm-uuid"` </ins> } Network struct { // PublicNetwork is name of the network the VMs are joined to. PublicNetwork string `gcfg:"public-network"` } Disk struct { // SCSIControllerType defines SCSI controller to be used. SCSIControllerType string `dcfg:"scsicontrollertype"`

// Returns the name of the VM on which this code is running. // Prerequisite: this code assumes VMWare vmtools or open-vm-tools to be installed in the VM. <ins> // Will attempt to determine the machine's name via it's UUID in this precedence order, failing if neither have a UUID: // * cloud config value VMUUID // * sysfs entry </ins> func getVMName(client *govmomi.Client, cfg *VSphereConfig) (string, error) { <del> addrs, err := net.InterfaceAddrs() if err != nil { return "", err </del> <ins> var vmUUID string if cfg.Global.VMUUID != "" { vmUUID = cfg.Global.VMUUID } else { // This needs root privileges on the host, and will fail otherwise. vmUUIDbytes, err := ioutil.ReadFile("/sys/devices/virtual/dmi/id/product_uuid") if err != nil { return "", err } vmUUID = string(vmUUIDbytes) cfg.Global.VMUUID = vmUUID </ins> } <del> if len(addrs) == 0 { return "", fmt.Errorf("unable to retrieve Instance ID") </del> <ins> if vmUUID == "" { return "", fmt.Errorf("unable to determine machine ID from cloud configuration or sysfs") </ins> } // Create context

s := object.NewSearchIndex(client.Client) <del> var svm object.Reference for _, v := range addrs { ip, _, err := net.ParseCIDR(v.String()) if err != nil { return "", fmt.Errorf("unable to parse cidr from ip") } // Finds a virtual machine or host by IP address. svm, err = s.FindByIp(ctx, dc, ip.String(), true) if err == nil && svm != nil { break } } if svm == nil { return "", fmt.Errorf("unable to retrieve vm reference from vSphere") </del> <ins> svm, err := s.FindByUuid(ctx, dc, strings.ToLower(strings.TrimSpace(vmUUID)), true, nil) if err != nil { return "", err </ins> } var vm mo.VirtualMachine <del> err = s.Properties(ctx, svm.Reference(), []string{"name", "resourcePool"}, &vm) </del> <ins> err = s.Properties(ctx, svm.Reference(), []string{"name"}, &vm) </ins> if err != nil { return "", err } return vm.Name, nil }

password = password insecure-flag = true datacenter = us-west <ins> vm-uuid = 1234 </ins> `)) if err != nil { t.Fatalf("Should succeed when a valid config is provided: %s", err)

if cfg.Global.Datacenter != "us-west" { t.Errorf("incorrect datacenter: %s", cfg.Global.Datacenter) } <ins> if cfg.Global.VMUUID != "1234" { t.Errorf("incorrect vm-uuid: %s", cfg.Global.VMUUID) } </ins> } func TestNewVSphere(t *testing.T) {