{"record":{"id":"5d337b918adc4b75","repo":"kubernetes/kops","slug":"spotinst-found-multiple-role-tags-q-vs-q","errorCode":null,"errorMessage":"spotinst: found multiple role tags %q vs %q","messagePattern":"spotinst: found multiple role tags %q vs %q","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go","lineNumber":1529,"sourceCode":"\n\t// Image.\n\tif e.ImageID != nil {\n\t\timage, err := resolveImage(cloud, fi.ValueOf(e.ImageID))\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\ttf.ImageID = image.ImageId\n\t}\n\n\tvar role string\n\tfor key := range e.Tags {\n\t\tif strings.HasPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix) {\n\t\t\tsuffix := strings.TrimPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix)\n\t\t\tif suffix == \"master\" {\n\t\t\t\tsuffix = \"control-plane\"\n\t\t\t}\n\t\t\tif role != \"\" && role != suffix {\n\t\t\t\treturn fmt.Errorf(\"spotinst: found multiple role tags %q vs %q\", role, suffix)\n\t\t\t}\n\t\t\trole = suffix\n\t\t}\n\t}\n\n\t// Security groups.\n\tif e.SecurityGroups != nil {\n\t\tfor _, sg := range e.SecurityGroups {\n\t\t\ttf.SecurityGroups = append(tf.SecurityGroups, sg.TerraformLink())\n\t\t\tif role != \"\" {\n\t\t\t\tif err := t.AddOutputVariableArray(role+\"_security_groups\", sg.TerraformLink()); err != nil {\n\t\t\t\t\treturn err\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// User data.","sourceCodeStart":1511,"sourceCodeEnd":1547,"githubUrl":"https://github.com/kubernetes/kops/blob/4c8573c808a73d578c5eadc86d410646ea0b0d73/upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go#L1511-L1547","documentation":"While mapping AWS tags on an instance to an instance-group role (in the spotinst elastigroup task's tag-discovery path), kOps finds more than one tag prefixed with CloudTagInstanceGroupRolePrefix carrying different role suffixes. The role suffix \"master\" is normalized to \"control-plane\" before comparison. This indicates contradictory role tags on the resource.","triggerScenarios":"The iteration over tags encounters two keys like KubernetesCluster/<cluster>-role-control-plane and ...-role-master (or node vs control-plane) on the same object with differing suffixes, so role != \"\" && role != suffix fires.","commonSituations":"Cluster upgraded from kOps versions that used \"master\" tags to the newer \"control-plane\" tag where both tags linger on an instance/security group; hand-edited tags in the AWS console; copied tags between instance groups.","solutions":["Inspect the resource's AWS tags and delete the stale duplicate role tag (e.g. the old \"master\" tag) so exactly one role tag remains.","Re-run `kops update cluster` to let kOps rewrite tags consistently.","If tags were manually edited, restore the tag set kOps expects for that instance group.","For post-1.24 clusters, ensure no legacy kubernetes.io/cluster/...-role-master tags are copied onto spotinst-managed resources."],"exampleFix":"// before: both tags on the instance\nKubernetesCluster/example-cluster-role-master, value=control-plane\nKubernetesCluster/example-cluster-role-control-plane, value=control-plane\n// after: single normalized tag\nKubernetesCluster/example-cluster-role-control-plane, value=control-plane","handlingStrategy":"validation","validationCode":"// enforce a single role tag per resource before reconciliation\nrole := \"\"\nfor key := range tags {\n    if strings.HasPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix) {\n        suffix := strings.TrimPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix)\n        if suffix == \"master\" { suffix = \"control-plane\" }\n        if role != \"\" && role != suffix {\n            return fmt.Errorf(\"conflicting role tags %q vs %q — remove the legacy tag\", role, suffix)\n        }\n        role = suffix\n    }\n}","typeGuard":null,"tryCatchPattern":"role, err := roleFromTags(tags)\nif err != nil {\n    klog.Warningf(\"skipping resource with conflicting role tags: %v\", err)\n    continue // skip instead of aborting the whole reconciliation\n}","preventionTips":["After kOps upgrades, clean up legacy -role-master tags on instances/SGs","Never copy role tags between instance groups manually","Audit tags with `aws ec2 describe-tags` filtering the role prefix","Let kOps manage tags rather than editing them in the console"],"tags":["spotinst","aws","iam-roles","tags","validation"],"backgroundTag":"conflicting-role-tags","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"}