kubernetes/kops · error

found IAM instance profile assigned to multiple Instance Gro

Error message

found IAM instance profile assigned to multiple Instance Group roles %v and %v: %v

What it means

During cluster model building, kOps allows a single pre-existing IAM instance profile (specified via spec.iam.profile on an InstanceGroup) to be shared, but only by Instance Groups that have the SAME InstanceGroupRole (e.g. two Node groups). If the same profile ARN appears on Instance Groups with different roles, the generated IAM policy documents would conflict, so Build aborts with this error listing both roles and the offending ARN.

Source

Thrown at pkg/model/awsmodel/iam.go:70

      "Effect": "Allow",
      "Principal": { "Service": "{{ IAMServiceEC2 }}"},
      "Action": "sts:AssumeRole"
    }
  ]
}`

func (b *IAMModelBuilder) Build(c *fi.CloudupModelBuilderContext) error {
	// Collect managed Instance Group roles
	managedRoles := make(map[kops.InstanceGroupRole]bool)

	// Collect Instance Profile ARNs and their associated Instance Group roles
	sharedProfileARNsToIGRole := make(map[string]kops.InstanceGroupRole)
	for _, ig := range b.AllInstanceGroups {
		if ig.Spec.IAM != nil && ig.Spec.IAM.Profile != nil {
			specProfile := fi.ValueOf(ig.Spec.IAM.Profile)
			if matchingRole, ok := sharedProfileARNsToIGRole[specProfile]; ok {
				if matchingRole != ig.Spec.Role {
					return fmt.Errorf("found IAM instance profile assigned to multiple Instance Group roles %v and %v: %v",
						ig.Spec.Role, sharedProfileARNsToIGRole[specProfile], specProfile)
				}
			} else {
				sharedProfileARNsToIGRole[specProfile] = ig.Spec.Role
			}
		} else {
			managedRoles[ig.Spec.Role] = true
		}
	}

	// Generate IAM tasks for each shared role
	for profileARN, igRole := range sharedProfileARNsToIGRole {
		lchPermissions := false
		defaultWarmPool := b.Cluster.Spec.CloudProvider.AWS.WarmPool
		for _, ig := range b.InstanceGroups {
			warmPool := defaultWarmPool.ResolveDefaults(ig)
			if ig.Spec.Role == igRole && warmPool.IsEnabled() && warmPool.EnableLifecycleHook {
				lchPermissions = true

View on GitHub (pinned to 4c8573c808)

Solutions

  1. Give each role its own instance profile: set a distinct spec.iam.profile ARN per InstanceGroup role.
  2. If the groups should truly share an identity, make their spec.role identical (e.g. both Node).
  3. Remove spec.iam.profile from one group so it falls back to the kOps-managed profile for its role.

Example fix

// before
apiVersion: kops.k8s.io/v1alpha2
kind: InstanceGroup
metadata:
  name: control-plane-1
spec:
  role: ControlPlane
  iam:
    profile: arn:aws:iam::123456789012:instance-profile/shared
---
kind: InstanceGroup
metadata:
  name: nodes-1
spec:
  role: Node
  iam:
    profile: arn:aws:iam::123456789012:instance-profile/shared
// after
spec:
  role: Node
  iam:
    profile: arn:aws:iam::123456789012:instance-profile/nodes-profile
Defensive patterns

Strategy: validation

Validate before calling

profiles := map[string]string{}
for _, ig := range instanceGroups {
	if ig.Spec.IAM != nil && ig.Spec.IAM.Profile != nil {
		arn := fi.ValueOf(ig.Spec.IAM.Profile)
		if prev, ok := profiles[arn]; ok && prev != string(ig.Spec.Role) {
			return fmt.Errorf("profile %s shared across roles %s and %s", arn, prev, ig.Spec.Role)
		}
		profiles[arn] = string(ig.Spec.Role)
	}
}

Prevention

When it happens

Trigger: Running `kops update cluster` / `kops edit cluster` when two or more InstanceGroups set spec.iam.profile to the same ARN while their spec.role values differ (e.g. one Node group and one ControlPlane group both point at the same instance profile ARN).

Common situations: Copy-pasting an existing profile ARN into a new instance group manifest and forgetting to change the role; consolidating groups to save IAM resources; migrating from managed to custom profiles on only part of the cluster.

Related errors


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