kubernetes/kops · error
spotinst: found multiple role tags %q vs %q
Error message
spotinst: found multiple role tags %q vs %q
What it means
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.
Source
Thrown at upup/pkg/fi/cloudup/spotinsttasks/elastigroup.go:1529
// Image.
if e.ImageID != nil {
image, err := resolveImage(cloud, fi.ValueOf(e.ImageID))
if err != nil {
return err
}
tf.ImageID = image.ImageId
}
var role string
for key := range e.Tags {
if strings.HasPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix) {
suffix := strings.TrimPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix)
if suffix == "master" {
suffix = "control-plane"
}
if role != "" && role != suffix {
return fmt.Errorf("spotinst: found multiple role tags %q vs %q", role, suffix)
}
role = suffix
}
}
// Security groups.
if e.SecurityGroups != nil {
for _, sg := range e.SecurityGroups {
tf.SecurityGroups = append(tf.SecurityGroups, sg.TerraformLink())
if role != "" {
if err := t.AddOutputVariableArray(role+"_security_groups", sg.TerraformLink()); err != nil {
return err
}
}
}
}
// User data.View on GitHub (pinned to 4c8573c808)
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.
Example fix
// before: both tags on the instance KubernetesCluster/example-cluster-role-master, value=control-plane KubernetesCluster/example-cluster-role-control-plane, value=control-plane // after: single normalized tag KubernetesCluster/example-cluster-role-control-plane, value=control-plane
Defensive patterns
Strategy: validation
Validate before calling
// enforce a single role tag per resource before reconciliation
role := ""
for key := range tags {
if strings.HasPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix) {
suffix := strings.TrimPrefix(key, awstasks.CloudTagInstanceGroupRolePrefix)
if suffix == "master" { suffix = "control-plane" }
if role != "" && role != suffix {
return fmt.Errorf("conflicting role tags %q vs %q — remove the legacy tag", role, suffix)
}
role = suffix
}
} Try / catch
role, err := roleFromTags(tags)
if err != nil {
klog.Warningf("skipping resource with conflicting role tags: %v", err)
continue // skip instead of aborting the whole reconciliation
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- error building cloud tags: %v
- spotinst: load balancer %q has no LoadBalancerName
- spotinst: found multiple role tags %q vs %q
- provider ID cannot be empty
- --region is required (when --external)
AI-assisted analysis of kubernetes/kops@4c8573c808 (2026-09-05).
Data as JSON: /api/errors/5d337b918adc4b75.
Report an issue: GitHub.