Read AWS Region from EC2 Metadata

Tackles kubernetes/autoscaler#1208. EC2 Metadata helpfully supplies AWS
Region info, so rather than _requiring_ an environment variable, this
patch enables `aws_manager.go` to retrieve that information from EC2
itself.

Example YAMLs no longer reference the vestigial `AWS_REGION` environment
variable, but supplying it to `cluster-autoscaler` still relays it to
the AWS SDK like before.
This commit is contained in:
Shatil Rafiullah 2018-09-28 22:45:34 -07:00
parent e14f2670e9
commit a36f8007af
6 changed files with 44 additions and 13 deletions

View File

@ -22,11 +22,13 @@ import (
"fmt" "fmt"
"io" "io"
"math/rand" "math/rand"
"os"
"regexp" "regexp"
"strings" "strings"
"time" "time"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/ec2metadata"
"github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/autoscaling" "github.com/aws/aws-sdk-go/service/autoscaling"
"github.com/aws/aws-sdk-go/service/ec2" "github.com/aws/aws-sdk-go/service/ec2"
@ -64,6 +66,18 @@ type asgTemplate struct {
Tags []*autoscaling.TagDescription Tags []*autoscaling.TagDescription
} }
// getRegion deduces the current AWS Region.
func getRegion(cfg ...*aws.Config) string {
region, present := os.LookupEnv("AWS_REGION")
if !present {
svc := ec2metadata.New(session.New(), cfg...)
if r, err := svc.Region(); err == nil {
region = r
}
}
return region
}
// createAwsManagerInternal allows for a customer autoScalingWrapper to be passed in by tests // createAwsManagerInternal allows for a customer autoScalingWrapper to be passed in by tests
func createAWSManagerInternal( func createAWSManagerInternal(
configReader io.Reader, configReader io.Reader,
@ -80,7 +94,7 @@ func createAWSManagerInternal(
} }
if autoScalingService == nil || ec2Service == nil { if autoScalingService == nil || ec2Service == nil {
sess := session.New() sess := session.New(aws.NewConfig().WithRegion(getRegion()))
if autoScalingService == nil { if autoScalingService == nil {
autoScalingService = &autoScalingWrapper{autoscaling.New(sess)} autoScalingService = &autoScalingWrapper{autoscaling.New(sess)}

View File

@ -18,6 +18,9 @@ package aws
import ( import (
"fmt" "fmt"
"net/http"
"net/http/httptest"
"os"
"testing" "testing"
"github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws"
@ -30,6 +33,32 @@ import (
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis" kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
) )
// TestGetRegion ensures correct source supplies AWS Region.
func TestGetRegion(t *testing.T) {
key := "AWS_REGION"
originalRegion, originalPresent := os.LookupEnv(key)
defer func(region string, present bool) {
os.Unsetenv(key)
if present {
os.Setenv(key, region)
}
}(originalRegion, originalPresent)
// Ensure environment variable retains precedence.
expected1 := "the-shire-1"
os.Setenv(key, expected1)
assert.Equal(t, expected1, getRegion())
// Ensure without environment variable, EC2 Metadata used... and it merely
// chops the last character off the Availability Zone.
expected2 := "mordor-2"
expected2a := expected2 + "a"
os.Unsetenv(key)
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte(expected2a))
}))
cfg := aws.NewConfig().WithEndpoint(server.URL)
assert.Equal(t, expected2, getRegion(cfg))
}
func TestBuildGenericLabels(t *testing.T) { func TestBuildGenericLabels(t *testing.T) {
labels := buildGenericLabels(&asgTemplate{ labels := buildGenericLabels(&asgTemplate{
InstanceType: &instanceType{ InstanceType: &instanceType{

View File

@ -138,9 +138,6 @@ spec:
- --skip-nodes-with-local-storage=false - --skip-nodes-with-local-storage=false
- --expander=least-waste - --expander=least-waste
- --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<YOUR CLUSTER NAME> - --node-group-auto-discovery=asg:tag=k8s.io/cluster-autoscaler/enabled,k8s.io/cluster-autoscaler/<YOUR CLUSTER NAME>
env:
- name: AWS_REGION
value: us-east-1
volumeMounts: volumeMounts:
- name: ssl-certs - name: ssl-certs
mountPath: /etc/ssl/certs/ca-certificates.crt mountPath: /etc/ssl/certs/ca-certificates.crt

View File

@ -139,9 +139,6 @@ spec:
- --expander=least-waste - --expander=least-waste
- --nodes=1:10:k8s-worker-asg-1 - --nodes=1:10:k8s-worker-asg-1
- --nodes=1:3:k8s-worker-asg-2 - --nodes=1:3:k8s-worker-asg-2
env:
- name: AWS_REGION
value: us-east-1
volumeMounts: volumeMounts:
- name: ssl-certs - name: ssl-certs
mountPath: /etc/ssl/certs/ca-certificates.crt mountPath: /etc/ssl/certs/ca-certificates.crt

View File

@ -137,9 +137,6 @@ spec:
- --cloud-provider=aws - --cloud-provider=aws
- --skip-nodes-with-local-storage=false - --skip-nodes-with-local-storage=false
- --nodes=1:10:k8s-worker-asg-1 - --nodes=1:10:k8s-worker-asg-1
env:
- name: AWS_REGION
value: us-east-1
volumeMounts: volumeMounts:
- name: ssl-certs - name: ssl-certs
mountPath: /etc/ssl/certs/ca-certificates.crt mountPath: /etc/ssl/certs/ca-certificates.crt

View File

@ -144,9 +144,6 @@ spec:
- --cloud-provider=aws - --cloud-provider=aws
- --skip-nodes-with-local-storage=false - --skip-nodes-with-local-storage=false
- --nodes={{ node_asg_min }}:{{ node_asg_max }}:{{ name }} - --nodes={{ node_asg_min }}:{{ node_asg_max }}:{{ name }}
env:
- name: AWS_REGION
value: {{ region }}
volumeMounts: volumeMounts:
- name: ssl-certs - name: ssl-certs
mountPath: /etc/ssl/certs/ca-certificates.crt mountPath: /etc/ssl/certs/ca-certificates.crt