mirror of https://github.com/k3s-io/k3s
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 #35014pull/6/head
parent
f56b606985
commit
04b787b946
|
@ -18,6 +18,7 @@ go_library(
|
|||
"aws_utils.go",
|
||||
"device_allocator.go",
|
||||
"log_handler.go",
|
||||
"regions.go",
|
||||
"retry_handler.go",
|
||||
"sets_ippermissions.go",
|
||||
"volumes.go",
|
||||
|
@ -53,6 +54,7 @@ go_test(
|
|||
srcs = [
|
||||
"aws_test.go",
|
||||
"device_allocator_test.go",
|
||||
"regions_test.go",
|
||||
"retry_handler_test.go",
|
||||
],
|
||||
library = ":go_default_library",
|
||||
|
|
|
@ -48,7 +48,6 @@ import (
|
|||
"k8s.io/kubernetes/pkg/api/v1"
|
||||
"k8s.io/kubernetes/pkg/api/v1/service"
|
||||
"k8s.io/kubernetes/pkg/cloudprovider"
|
||||
awscredentials "k8s.io/kubernetes/pkg/credentialprovider/aws"
|
||||
"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
|
||||
const DefaultMaxEBSVolumes = 39
|
||||
|
||||
// Used to call awscredentials.Init() just once
|
||||
// Used to call RecognizeWellKnownRegions just once
|
||||
var once sync.Once
|
||||
|
||||
// Services is an abstraction over AWS, to allow mocking/other implementations
|
||||
|
@ -691,6 +690,7 @@ func init() {
|
|||
},
|
||||
&credentials.SharedCredentialsProvider{},
|
||||
})
|
||||
|
||||
aws := newAWSSDKProvider(creds)
|
||||
return newAWSCloud(config, aws)
|
||||
})
|
||||
|
@ -732,15 +732,6 @@ func getAvailabilityZone(metadata EC2Metadata) (string, error) {
|
|||
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.
|
||||
// Returns an error if the az is known invalid (empty)
|
||||
func azToRegion(az string) (string, error) {
|
||||
|
@ -777,9 +768,14 @@ func newAWSCloud(config io.Reader, awsServices Services) (*Cloud, error) {
|
|||
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 {
|
||||
valid := isRegionValid(regionName)
|
||||
if !valid {
|
||||
// This _should_ now be unreachable, given we call RecognizeRegion
|
||||
return nil, fmt.Errorf("not a valid AWS zone (unknown region): %s", zone)
|
||||
}
|
||||
} else {
|
||||
|
@ -848,9 +844,9 @@ func newAWSCloud(config io.Reader, awsServices Services) (*Cloud, error) {
|
|||
glog.Infof("AWS cloud - no tag filtering")
|
||||
}
|
||||
|
||||
// Register handler for ECR credentials
|
||||
// Register regions, in particular for ECR credentials
|
||||
once.Do(func() {
|
||||
awscredentials.Init()
|
||||
RecognizeWellKnownRegions()
|
||||
})
|
||||
|
||||
return awsCloud, nil
|
||||
|
|
|
@ -210,11 +210,6 @@ func TestNewAWSCloud(t *testing.T) {
|
|||
nil, NewFakeAWSServices().withAz(""),
|
||||
true, "",
|
||||
},
|
||||
{
|
||||
"Config specified invalid zone",
|
||||
strings.NewReader("[global]\nzone = blahonga"), NewFakeAWSServices(),
|
||||
true, "",
|
||||
},
|
||||
{
|
||||
"Config specifies valid zone",
|
||||
strings.NewReader("[global]\nzone = eu-west-1a"), NewFakeAWSServices(),
|
||||
|
|
|
@ -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)
|
||||
}
|
|
@ -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"
|
||||
)
|
||||
|
||||
// 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"
|
||||
|
||||
// awsHandlerLogger is a handler that logs all AWS SDK requests
|
||||
|
@ -101,21 +80,20 @@ type ecrProvider struct {
|
|||
|
||||
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
|
||||
// impossible, that we'll use more than one.
|
||||
// Not using the package init() function: this module should be initialized only
|
||||
// if using the AWS cloud provider. This way, we avoid timeouts waiting for a
|
||||
// non-existent provider.
|
||||
func Init() {
|
||||
for _, region := range AWSRegions {
|
||||
credentialprovider.RegisterCredentialProvider("aws-ecr-"+region,
|
||||
&lazyEcrProvider{
|
||||
region: region,
|
||||
regionURL: fmt.Sprintf(registryURLTemplate, region),
|
||||
})
|
||||
}
|
||||
// This should be called only if using the AWS cloud provider.
|
||||
// This way, we avoid timeouts waiting for a non-existent provider.
|
||||
func RegisterCredentialsProvider(region string) {
|
||||
glog.V(4).Infof("registering credentials provider for AWS region %q", region)
|
||||
|
||||
credentialprovider.RegisterCredentialProvider("aws-ecr-"+region,
|
||||
&lazyEcrProvider{
|
||||
region: region,
|
||||
regionURL: fmt.Sprintf(registryURLTemplate, region),
|
||||
})
|
||||
}
|
||||
|
||||
// Enabled implements DockerConfigProvider.Enabled for the lazy provider.
|
||||
|
|
Loading…
Reference in New Issue