From b1079f881363acc6bc5fc3b9bb816a41ec172ae0 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sat, 18 Feb 2017 23:59:26 -0500 Subject: [PATCH] AWS: Skip instances that are taggged as a master We recognize a few AWS tags, and skip over masters when finding zones for dynamic volumes. This will fix #34583. This is not perfect, in that really the scheduler is the only component that can correctly choose the zone, but should address the common problem. --- pkg/cloudprovider/providers/aws/aws.go | 27 +++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/pkg/cloudprovider/providers/aws/aws.go b/pkg/cloudprovider/providers/aws/aws.go index d3f9456767b..2fa79f48ca8 100644 --- a/pkg/cloudprovider/providers/aws/aws.go +++ b/pkg/cloudprovider/providers/aws/aws.go @@ -157,6 +157,10 @@ const ( createTagSteps = 9 ) +// awsTagNameMasterRoles is a set of well-known AWS tag names that indicate the instance is a master +// The major consequence is that it is then not considered for AWS zone discovery for dynamic volume creation. +var awsTagNameMasterRoles = sets.NewString("kubernetes.io/role/master", "k8s.io/role/master") + // Maps from backend protocol to ELB protocol var backendProtocolMapping = map[string]string{ "https": "https", @@ -1040,9 +1044,9 @@ func (c *Cloud) getInstancesByRegex(regex string) ([]types.NodeName, error) { return matchingInstances, nil } -// getAllZones retrieves a list of all the zones in which nodes are running +// getCandidateZonesForDynamicVolume retrieves a list of all the zones in which nodes are running // It currently involves querying all instances -func (c *Cloud) getAllZones() (sets.String, error) { +func (c *Cloud) getCandidateZonesForDynamicVolume() (sets.String, error) { // We don't currently cache this; it is currently used only in volume // creation which is expected to be a comparatively rare occurrence. @@ -1066,10 +1070,19 @@ func (c *Cloud) getAllZones() (sets.String, error) { zones := sets.NewString() for _, instance := range instances { - // Only return fully-ready instances when listing instances - // (vs a query by name, where we will return it if we find it) - if orEmpty(instance.State.Name) == "pending" { - glog.V(2).Infof("Skipping EC2 instance (pending): %s", *instance.InstanceId) + // We skip over master nodes, if the installation tool labels them with one of the well-known master labels + // This avoids creating a volume in a zone where only the master is running - e.g. #34583 + // This is a short-term workaround until the scheduler takes care of zone selection + master := false + for _, tag := range instance.Tags { + tagKey := aws.StringValue(tag.Key) + if awsTagNameMasterRoles.Has(tagKey) { + master = true + } + } + + if master { + glog.V(4).Infof("Ignoring master instance %q in zone discovery", aws.StringValue(instance.InstanceId)) continue } @@ -1583,7 +1596,7 @@ func (c *Cloud) DetachDisk(diskName KubernetesVolumeID, nodeName types.NodeName) // CreateDisk implements Volumes.CreateDisk func (c *Cloud) CreateDisk(volumeOptions *VolumeOptions) (KubernetesVolumeID, error) { - allZones, err := c.getAllZones() + allZones, err := c.getCandidateZonesForDynamicVolume() if err != nil { return "", fmt.Errorf("error querying for all zones: %v", err) }