kubernetes/kops · error

failed to get local-ipv4 address from ec2 metadata: %w

Error message

failed to get local-ipv4 address from ec2 metadata: %w

What it means

After loading AWS config, GetMetadataLocalIP queries EC2 IMDS for local-ipv4 via getMetadata; any failure (timeout, 404, IMDSv2 token error) is wrapped with this message. nodeup needs this IP as the node's internal address (e.g. for server certs and systemd env files).

Source

Thrown at nodeup/pkg/model/context.go:600

// RunningOnAzure returns true if we are running on Azure
func (c *NodeupModelContext) RunningOnAzure() bool {
	return c.CloudProvider() == kops.CloudProviderAzure
}

// GetMetadataLocalIP returns the local IP address read from metadata
func (c *NodeupModelContext) GetMetadataLocalIP(ctx context.Context) (string, error) {
	var internalIP string

	switch c.BootConfig.CloudProvider {
	case kops.CloudProviderAWS:
		config, err := awsconfig.LoadDefaultConfig(ctx)
		if err != nil {
			return "", fmt.Errorf("failed to load AWS config: %w", err)
		}
		metadata := imds.NewFromConfig(config)
		localIPv4, err := getMetadata(ctx, metadata, "local-ipv4")
		if err != nil {
			return "", fmt.Errorf("failed to get local-ipv4 address from ec2 metadata: %w", err)
		}
		internalIP = localIPv4

	case kops.CloudProviderHetzner:
		client := hcloudmetadata.NewClient()
		privateNetworksYaml, err := client.PrivateNetworks()
		if err != nil {
			return "", fmt.Errorf("failed to get private networks from hetzner cloud metadata: %w", err)
		}
		var privateNetworks []struct {
			IP           net.IP   `json:"ip"`
			AliasIPs     []net.IP `json:"alias_ips"`
			InterfaceNum int      `json:"interface_num"`
			MACAddress   string   `json:"mac_address"`
			NetworkID    int      `json:"network_id"`
			NetworkName  string   `json:"network_name"`
			Network      string   `json:"network"`
			Subnet       string   `json:"subnet"`

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Ensure instance metadata service is reachable: curl -s -H 'X-aws-ec2-metadata-token: ...' http://169.254.169.254/latest/meta-data/local-ipv4 from the node
  2. Raise IMDSv2 hop limit: `aws ec2 modify-instance-metadata-options --instance-id <id> --http-put-response-hop-limit 2`
  3. Check iptables/host firewall and security setup for rules dropping 169.254.169.254 traffic
  4. Retry nodeup — transient IMDS failures during rolling updates often resolve; check EC2 service health/region status
Defensive patterns

Strategy: retry

Validate before calling

// precheck: token + local-ipv4 fetch before nodeup
TOKEN=$(curl -sX PUT --max-time 2 'http://169.254.169.254/latest/api/token' -H 'X-aws-ec2-metadata-token-ttl-seconds: 60')
curl -s --max-time 2 -H "X-aws-ec2-metadata-token: $TOKEN" http://169.254.169.254/latest/meta-data/local-ipv4 || echo "IMDS local-ipv4 unreachable"

Try / catch

ip, err := c.GetMetadataLocalIP(ctx)
if err != nil {
    if strings.Contains(err.Error(), "local-ipv4") {
        // transient IMDS failure: nodeup retries internally; on persistent failure raise hop limit / check firewall
        return fmt.Errorf("IMDS local-ipv4 unavailable, verify metadata options and 169.254.169.254 egress: %w", err)
    }
    return err
}

Prevention

When it happens

Trigger: getMetadata(ctx, imds client, "local-ipv4") returns an error: IMDS unreachable (169.254.169.254 blocked), IMDSv2 token fetch fails due to hop limit, or the request times out during node bootstrap.

Common situations: Security groups/host firewall blocking link-local metadata; IMDSv2 hop limit of 1 when nodeup runs inside a container; transient IMDS throttling during mass rolling updates; non-EC2 environment misdetected as AWS.

Related errors


AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05). Data as JSON: /api/errors/fd8e5df1da6fbaa5. Report an issue: GitHub.