{"record":{"id":"c733d93176382d13","repo":"kubernetes/kops","slug":"finding-primary-network-interface-w","errorCode":null,"errorMessage":"finding primary network interface: %w","messagePattern":"finding primary network interface: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"nodeup/pkg/model/networking/eni_networking.go","lineNumber":163,"sourceCode":"// boot time. The file uses the udev property \"INTERFACE\" for this, because a negated \"Name=\"\n// test also agrees with the alternative names of an interface.\n//\n// The file name starts with 75. This puts the file after the per-interface files\n// (\"10-netplan-*\" on Debian, \"70-*\" on AL2023) and before the AL2023 catch-all file\n// \"80-ec2.network\". systemd-networkd uses the first file that agrees with an interface. Thus,\n// if the primary network interface has a per-interface file, systemd-networkd uses that file.\nfunc markSecondaryENIsUnmanaged(c *fi.NodeupModelBuilderContext, dist distributions.Distribution) error {\n\tif !(dist.IsAmazonLinux() ||\n\t\t(dist.IsDebian() && dist.Version() >= 12)) {\n\t\treturn nil\n\t}\n\n\tprimary, err := primaryInterfaceName(c.Context())\n\tif err != nil {\n\t\t// Do not make the file if the primary network interface is not known. A match that\n\t\t// includes the primary network interface causes systemd-networkd to ignore it, and\n\t\t// then systemd-resolved has no DNS servers for it.\n\t\treturn fmt.Errorf(\"finding primary network interface: %w\", err)\n\t}\n\n\tcontents := fmt.Sprintf(`\n[Match]\nDriver=ena\nProperty=!INTERFACE=%s\n\n[Link]\nUnmanaged=yes\n`, primary)\n\n\tc.AddTask(&nodetasks.File{\n\t\tPath:            \"/etc/systemd/network/75-eni-secondary.network\",\n\t\tContents:        fi.NewStringResource(contents),\n\t\tType:            nodetasks.FileType_File,\n\t\tAfterPackages:   true,\n\t\tOnChangeExecute: [][]string{{\"systemctl\", \"restart\", \"systemd-networkd\"}},\n\t})","sourceCodeStart":145,"sourceCodeEnd":181,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/nodeup/pkg/model/networking/eni_networking.go#L145-L181","documentation":"On AWS, markSecondaryENIsUnmanaged writes a systemd-networkd config that leaves the primary ENI managed; it first resolves the primary interface name via primaryInterfaceName, which queries EC2 IMDS for the primary MAC and matches it against /sys/class/net physical interfaces. Any failure there (IMDS unavailable, no matching interface, multiple matches) is wrapped in this error.","triggerScenarios":"primaryInterfaceName(c.Context()) fails during nodeup Build on an AWS instance: IMDS 'mac' metadata request fails (IMDSv2 hop limit, IMDS disabled, network timeout), no physical interface in /sys/class/net matches the primary MAC, or more than one matches.","commonSituations":"Instances with IMDS access blocked (metadata-options http-tokens/put-response-hop-limit misconfig); bond/team setups where the primary MAC belongs to multiple entries; unusual ENA interface naming; running nodeup outside a real EC2 instance.","solutions":["Verify IMDS is reachable: curl -H 'X-aws-ec2-metadata-token: ...' http://169.254.169.254/latest/meta-data/mac","Raise the IMDSv2 hop limit if nested/containers are involved: aws ec2 modify-instance-metadata-options --http-put-response-hop-limit 2","Ensure exactly one physical interface in /sys/class/net has the primary MAC (remove bonds/extra virtual devices or fix their MACs)","Confirm the instance has an ENA primary interface and the nodeup context is a real EC2 instance"],"exampleFix":"// before\naws ec2 modify-instance-metadata-options --instance-id i-123 --http-tokens required --http-put-response-hop-limit 1\n// after\naws ec2 modify-instance-metadata-options --instance-id i-123 --http-put-response-hop-limit 2","handlingStrategy":"validation","validationCode":"mac, err := imdsFetch(\"mac\") // curl IMDS with IMDSv2 token\nif err != nil {\n    return fmt.Errorf(\"IMDS unreachable; markSecondaryENIsUnmanaged would fail: %w\", err)\n}\nmatches := 0\nentries, _ := os.ReadDir(\"/sys/class/net\")\nfor _, e := range entries {\n    if addr, err := os.ReadFile(\"/sys/class/net/\" + e.Name() + \"/address\"); err == nil &&\n        strings.EqualFold(strings.TrimSpace(string(addr)), mac) {\n        matches++\n    }\n}\nif matches != 1 {\n    return fmt.Errorf(\"expected exactly 1 interface with MAC %s, found %d\", mac, matches)\n}","typeGuard":null,"tryCatchPattern":"primary, err := primaryInterfaceName(c.Context())\nif err != nil {\n    klog.Warningf(\"skipping secondary-ENI unmanaged file: %v\", err) // caller already chose not to write the file\n    return nil\n}","preventionTips":["Set IMDSv2 hop limit ≥ 2 where containers/nested envs need metadata","Do not disable IMDS on kops worker nodes","Avoid bonding the primary ENA interface so exactly one physical NIC matches the primary MAC"],"tags":["nodeup","aws","eni","imds","networkd"],"backgroundTag":"primary-interface-detection-failed","analyzedSha":"4c8573c808a73d578c5eadc86d410646ea0b0d73","analyzedAt":"2026-09-05T04:13:19.212Z","contentChangedAt":"2026-09-05T04:13:19.212Z","schemaVersion":2},"datasetVersion":"2026-09-12T07:17:12.445Z"}