AWS: trust region if found from AWS metadata
Means we can run in newly announced regions without a code change. We don't register the ECR provider in new regions, so we will still need a code change for now. This also means we do trust config / instance metadata, and don't reject incorrectly configured zones. Fix #35014
This commit is contained in:
parent
f56b606985
commit
04b787b946
@ -18,6 +18,7 @@ go_library(
|
|||||||
"aws_utils.go",
|
"aws_utils.go",
|
||||||
"device_allocator.go",
|
"device_allocator.go",
|
||||||
"log_handler.go",
|
"log_handler.go",
|
||||||
|
"regions.go",
|
||||||
"retry_handler.go",
|
"retry_handler.go",
|
||||||
"sets_ippermissions.go",
|
"sets_ippermissions.go",
|
||||||
"volumes.go",
|
"volumes.go",
|
||||||
@ -53,6 +54,7 @@ go_test(
|
|||||||
srcs = [
|
srcs = [
|
||||||
"aws_test.go",
|
"aws_test.go",
|
||||||
"device_allocator_test.go",
|
"device_allocator_test.go",
|
||||||
|
"regions_test.go",
|
||||||
"retry_handler_test.go",
|
"retry_handler_test.go",
|
||||||
],
|
],
|
||||||
library = ":go_default_library",
|
library = ":go_default_library",
|
||||||
|
@ -48,7 +48,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api/v1"
|
"k8s.io/kubernetes/pkg/api/v1"
|
||||||
"k8s.io/kubernetes/pkg/api/v1/service"
|
"k8s.io/kubernetes/pkg/api/v1/service"
|
||||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||||
awscredentials "k8s.io/kubernetes/pkg/credentialprovider/aws"
|
|
||||||
"k8s.io/kubernetes/pkg/volume"
|
"k8s.io/kubernetes/pkg/volume"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -182,7 +181,7 @@ const DefaultVolumeType = "gp2"
|
|||||||
// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volume_limits.html#linux-specific-volume-limits
|
// See http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/volume_limits.html#linux-specific-volume-limits
|
||||||
const DefaultMaxEBSVolumes = 39
|
const DefaultMaxEBSVolumes = 39
|
||||||
|
|
||||||
// Used to call awscredentials.Init() just once
|
// Used to call RecognizeWellKnownRegions just once
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
// Services is an abstraction over AWS, to allow mocking/other implementations
|
// Services is an abstraction over AWS, to allow mocking/other implementations
|
||||||
@ -691,6 +690,7 @@ func init() {
|
|||||||
},
|
},
|
||||||
&credentials.SharedCredentialsProvider{},
|
&credentials.SharedCredentialsProvider{},
|
||||||
})
|
})
|
||||||
|
|
||||||
aws := newAWSSDKProvider(creds)
|
aws := newAWSSDKProvider(creds)
|
||||||
return newAWSCloud(config, aws)
|
return newAWSCloud(config, aws)
|
||||||
})
|
})
|
||||||
@ -732,15 +732,6 @@ func getAvailabilityZone(metadata EC2Metadata) (string, error) {
|
|||||||
return metadata.GetMetadata("placement/availability-zone")
|
return metadata.GetMetadata("placement/availability-zone")
|
||||||
}
|
}
|
||||||
|
|
||||||
func isRegionValid(region string) bool {
|
|
||||||
for _, r := range awscredentials.AWSRegions {
|
|
||||||
if r == region {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Derives the region from a valid az name.
|
// Derives the region from a valid az name.
|
||||||
// Returns an error if the az is known invalid (empty)
|
// Returns an error if the az is known invalid (empty)
|
||||||
func azToRegion(az string) (string, error) {
|
func azToRegion(az string) (string, error) {
|
||||||
@ -777,9 +768,14 @@ func newAWSCloud(config io.Reader, awsServices Services) (*Cloud, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Trust that if we get a region from configuration or AWS metadata that it is valid,
|
||||||
|
// and register ECR providers
|
||||||
|
RecognizeRegion(regionName)
|
||||||
|
|
||||||
if !cfg.Global.DisableStrictZoneCheck {
|
if !cfg.Global.DisableStrictZoneCheck {
|
||||||
valid := isRegionValid(regionName)
|
valid := isRegionValid(regionName)
|
||||||
if !valid {
|
if !valid {
|
||||||
|
// This _should_ now be unreachable, given we call RecognizeRegion
|
||||||
return nil, fmt.Errorf("not a valid AWS zone (unknown region): %s", zone)
|
return nil, fmt.Errorf("not a valid AWS zone (unknown region): %s", zone)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -848,9 +844,9 @@ func newAWSCloud(config io.Reader, awsServices Services) (*Cloud, error) {
|
|||||||
glog.Infof("AWS cloud - no tag filtering")
|
glog.Infof("AWS cloud - no tag filtering")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register handler for ECR credentials
|
// Register regions, in particular for ECR credentials
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
awscredentials.Init()
|
RecognizeWellKnownRegions()
|
||||||
})
|
})
|
||||||
|
|
||||||
return awsCloud, nil
|
return awsCloud, nil
|
||||||
|
@ -210,11 +210,6 @@ func TestNewAWSCloud(t *testing.T) {
|
|||||||
nil, NewFakeAWSServices().withAz(""),
|
nil, NewFakeAWSServices().withAz(""),
|
||||||
true, "",
|
true, "",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"Config specified invalid zone",
|
|
||||||
strings.NewReader("[global]\nzone = blahonga"), NewFakeAWSServices(),
|
|
||||||
true, "",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"Config specifies valid zone",
|
"Config specifies valid zone",
|
||||||
strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(),
|
strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(),
|
||||||
|
94
pkg/cloudprovider/providers/aws/regions.go
Normal file
94
pkg/cloudprovider/providers/aws/regions.go
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/golang/glog"
|
||||||
|
"k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
awscredentialprovider "k8s.io/kubernetes/pkg/credentialprovider/aws"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
// WellKnownRegions is the complete list of regions known to the AWS cloudprovider
|
||||||
|
// and credentialprovider.
|
||||||
|
var WellKnownRegions = [...]string{
|
||||||
|
// from `aws ec2 describe-regions --region us-east-1 --query Regions[].RegionName | sort`
|
||||||
|
"ap-northeast-1",
|
||||||
|
"ap-northeast-2",
|
||||||
|
"ap-south-1",
|
||||||
|
"ap-southeast-1",
|
||||||
|
"ap-southeast-2",
|
||||||
|
"ca-central-1",
|
||||||
|
"eu-central-1",
|
||||||
|
"eu-west-1",
|
||||||
|
"eu-west-2",
|
||||||
|
"sa-east-1",
|
||||||
|
"us-east-1",
|
||||||
|
"us-east-2",
|
||||||
|
"us-west-1",
|
||||||
|
"us-west-2",
|
||||||
|
|
||||||
|
// these are not registered in many / most accounts
|
||||||
|
"cn-north-1",
|
||||||
|
"us-gov-west-1",
|
||||||
|
}
|
||||||
|
|
||||||
|
// awsRegionsMutex protects awsRegions
|
||||||
|
var awsRegionsMutex sync.Mutex
|
||||||
|
|
||||||
|
// awsRegions is a set of recognized regions
|
||||||
|
var awsRegions sets.String
|
||||||
|
|
||||||
|
// RecognizeRegion is called for each AWS region we know about.
|
||||||
|
// It currently registers a credential provider for that region.
|
||||||
|
// There are two paths to discovering a region:
|
||||||
|
// * we hard-code some well-known regions
|
||||||
|
// * if a region is discovered from instance metadata, we add that
|
||||||
|
func RecognizeRegion(region string) {
|
||||||
|
awsRegionsMutex.Lock()
|
||||||
|
defer awsRegionsMutex.Unlock()
|
||||||
|
|
||||||
|
if awsRegions == nil {
|
||||||
|
awsRegions = sets.NewString()
|
||||||
|
}
|
||||||
|
|
||||||
|
if awsRegions.Has(region) {
|
||||||
|
glog.V(6).Infof("found AWS region %q again - ignoring", region)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
glog.V(4).Infof("found AWS region %q", region)
|
||||||
|
|
||||||
|
awscredentialprovider.RegisterCredentialsProvider(region)
|
||||||
|
|
||||||
|
awsRegions.Insert(region)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RecognizeWellKnownRegions calls RecognizeRegion on each WellKnownRegion
|
||||||
|
func RecognizeWellKnownRegions() {
|
||||||
|
for _, region := range WellKnownRegions {
|
||||||
|
RecognizeRegion(region)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// isRegionValid checks if the region is in the set of known regions
|
||||||
|
func isRegionValid(region string) bool {
|
||||||
|
awsRegionsMutex.Lock()
|
||||||
|
defer awsRegionsMutex.Unlock()
|
||||||
|
|
||||||
|
return awsRegions.Has(region)
|
||||||
|
}
|
85
pkg/cloudprovider/providers/aws/regions_test.go
Normal file
85
pkg/cloudprovider/providers/aws/regions_test.go
Normal file
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package aws
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TestRegions does basic checking of region verification / addition
|
||||||
|
func TestRegions(t *testing.T) {
|
||||||
|
RecognizeWellKnownRegions()
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
Add string
|
||||||
|
Lookup string
|
||||||
|
ExpectIsRegion bool
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
Lookup: "us-east-1",
|
||||||
|
ExpectIsRegion: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Lookup: "us-east-1a",
|
||||||
|
ExpectIsRegion: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Add: "us-test-1",
|
||||||
|
Lookup: "us-east-1",
|
||||||
|
ExpectIsRegion: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Lookup: "us-test-1",
|
||||||
|
ExpectIsRegion: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Add: "us-test-1",
|
||||||
|
Lookup: "us-test-1",
|
||||||
|
ExpectIsRegion: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, test := range tests {
|
||||||
|
if test.Add != "" {
|
||||||
|
RecognizeRegion(test.Add)
|
||||||
|
}
|
||||||
|
|
||||||
|
if test.Lookup != "" {
|
||||||
|
if isRegionValid(test.Lookup) != test.ExpectIsRegion {
|
||||||
|
t.Fatalf("region valid mismatch: %q", test.Lookup)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TestRecognizesNewRegion verifies that we see a region from metadata, we recognize it as valid
|
||||||
|
func TestRecognizesNewRegion(t *testing.T) {
|
||||||
|
region := "us-testrecognizesnewregion-1"
|
||||||
|
if isRegionValid(region) {
|
||||||
|
t.Fatalf("region already valid: %q", region)
|
||||||
|
}
|
||||||
|
|
||||||
|
awsServices := NewFakeAWSServices().withAz(region + "a")
|
||||||
|
_, err := newAWSCloud(nil, awsServices)
|
||||||
|
if err != nil {
|
||||||
|
t.Errorf("error building AWS cloud: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !isRegionValid(region) {
|
||||||
|
t.Fatalf("newly discovered region not valid: %q", region)
|
||||||
|
}
|
||||||
|
}
|
@ -30,27 +30,6 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/credentialprovider"
|
"k8s.io/kubernetes/pkg/credentialprovider"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AWSRegions is the complete list of regions known to the AWS cloudprovider
|
|
||||||
// and credentialprovider.
|
|
||||||
var AWSRegions = [...]string{
|
|
||||||
"us-east-1",
|
|
||||||
"us-east-2",
|
|
||||||
"us-west-1",
|
|
||||||
"us-west-2",
|
|
||||||
"eu-west-1",
|
|
||||||
"eu-west-2",
|
|
||||||
"eu-central-1",
|
|
||||||
"ap-south-1",
|
|
||||||
"ap-southeast-1",
|
|
||||||
"ap-southeast-2",
|
|
||||||
"ap-northeast-1",
|
|
||||||
"ap-northeast-2",
|
|
||||||
"ca-central-1",
|
|
||||||
"cn-north-1",
|
|
||||||
"us-gov-west-1",
|
|
||||||
"sa-east-1",
|
|
||||||
}
|
|
||||||
|
|
||||||
const registryURLTemplate = "*.dkr.ecr.%s.amazonaws.com"
|
const registryURLTemplate = "*.dkr.ecr.%s.amazonaws.com"
|
||||||
|
|
||||||
// awsHandlerLogger is a handler that logs all AWS SDK requests
|
// awsHandlerLogger is a handler that logs all AWS SDK requests
|
||||||
@ -101,21 +80,20 @@ type ecrProvider struct {
|
|||||||
|
|
||||||
var _ credentialprovider.DockerConfigProvider = &ecrProvider{}
|
var _ credentialprovider.DockerConfigProvider = &ecrProvider{}
|
||||||
|
|
||||||
// Init creates a lazy provider for each AWS region, in order to support
|
// RegisterCredentialsProvider registers a credential provider for the specified region.
|
||||||
|
// It creates a lazy provider for each AWS region, in order to support
|
||||||
// cross-region ECR access. They have to be lazy because it's unlikely, but not
|
// cross-region ECR access. They have to be lazy because it's unlikely, but not
|
||||||
// impossible, that we'll use more than one.
|
// impossible, that we'll use more than one.
|
||||||
// Not using the package init() function: this module should be initialized only
|
// This should be called only if using the AWS cloud provider.
|
||||||
// if using the AWS cloud provider. This way, we avoid timeouts waiting for a
|
// This way, we avoid timeouts waiting for a non-existent provider.
|
||||||
// non-existent provider.
|
func RegisterCredentialsProvider(region string) {
|
||||||
func Init() {
|
glog.V(4).Infof("registering credentials provider for AWS region %q", region)
|
||||||
for _, region := range AWSRegions {
|
|
||||||
credentialprovider.RegisterCredentialProvider("aws-ecr-"+region,
|
|
||||||
&lazyEcrProvider{
|
|
||||||
region: region,
|
|
||||||
regionURL: fmt.Sprintf(registryURLTemplate, region),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
credentialprovider.RegisterCredentialProvider("aws-ecr-"+region,
|
||||||
|
&lazyEcrProvider{
|
||||||
|
region: region,
|
||||||
|
regionURL: fmt.Sprintf(registryURLTemplate, region),
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enabled implements DockerConfigProvider.Enabled for the lazy provider.
|
// Enabled implements DockerConfigProvider.Enabled for the lazy provider.
|
||||||
|
Loading…
Reference in New Issue
Block a user