Replace behavior for aws hostnameOverride

If the cluster's VPC includes DHCP options the local-hostname includes
the DHCP zone instead of the private DNS name from AWS (which is what
k8s uses regardless of flags). This patch simply makes the
hostnameOverride implementation match by using the AWS api to get the
private DNS name

Related to #7172
This commit is contained in:
Thomas Jackson 2019-06-21 15:48:33 -07:00
parent dd6b0314fc
commit ea61fb8de0
3 changed files with 62 additions and 26 deletions

View File

@ -59,8 +59,10 @@ go_library(
"//util/pkg/proxy:go_default_library",
"//util/pkg/reflectutils:go_default_library",
"//util/pkg/vfs:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws/ec2metadata:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/aws/session:go_default_library",
"//vendor/github.com/aws/aws-sdk-go/service/ec2:go_default_library",
"//vendor/github.com/blang/semver:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",

View File

@ -33,6 +33,10 @@ import (
"k8s.io/kops/util/pkg/vfs"
"k8s.io/kubernetes/pkg/util/mount"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/ec2"
"github.com/blang/semver"
"k8s.io/klog"
)
@ -534,25 +538,40 @@ func EvaluateHostnameOverride(hostnameOverride string) (string, error) {
return hostnameOverride, nil
}
// We recognize @aws as meaning "the local-hostname from the aws metadata service"
vBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/local-hostname")
// We recognize @aws as meaning "the private DNS name from AWS", to generate this we need to get a few pieces of information
azBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/placement/availability-zone")
if err != nil {
return "", fmt.Errorf("error reading local hostname from AWS metadata: %v", err)
return "", fmt.Errorf("error reading availability zone from AWS metadata: %v", err)
}
// The local-hostname gets it's hostname from the AWS DHCP Option Set, which
// may provide multiple hostnames separated by spaces. For now just choose
// the first one as the hostname.
domains := strings.Fields(string(vBytes))
if len(domains) == 0 {
klog.Warningf("Local hostname from AWS metadata service was empty")
return "", nil
instanceIDBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/instance-id")
if err != nil {
return "", fmt.Errorf("error reading instance-id from AWS metadata: %v", err)
}
domain := domains[0]
instanceID := string(instanceIDBytes)
klog.Infof("Using hostname from AWS metadata service: %s", domain)
config := aws.NewConfig()
config = config.WithCredentialsChainVerboseErrors(true)
return domain, nil
s, err := session.NewSession(config)
if err != nil {
return "", fmt.Errorf("error starting new AWS session: %v", err)
}
svc := ec2.New(s, config.WithRegion(string(azBytes[:len(azBytes)-1])))
result, err := svc.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIds: []*string{&instanceID},
})
if len(result.Reservations) != 1 {
return "", fmt.Errorf("Too many reservations returned for the single instance-id")
}
if len(result.Reservations[0].Instances) != 1 {
return "", fmt.Errorf("Too many instances returned for the single instance-id")
}
return *(result.Reservations[0].Instances[0].PrivateDnsName), nil
}
// FindCert is a helper method to retrieving a certificate from the store

View File

@ -441,25 +441,40 @@ func evaluateHostnameOverride(hostnameOverride string) (string, error) {
k = strings.ToLower(k)
if k == "@aws" {
// We recognize @aws as meaning "the local-hostname from the aws metadata service"
vBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/local-hostname")
// We recognize @aws as meaning "the private DNS name from AWS", to generate this we need to get a few pieces of information
azBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/placement/availability-zone")
if err != nil {
return "", fmt.Errorf("error reading local hostname from AWS metadata: %v", err)
return "", fmt.Errorf("error reading availability zone from AWS metadata: %v", err)
}
// The local-hostname gets it's hostname from the AWS DHCP Option Set, which
// may provide multiple hostnames separated by spaces. For now just choose
// the first one as the hostname.
domains := strings.Fields(string(vBytes))
if len(domains) == 0 {
klog.Warningf("Local hostname from AWS metadata service was empty")
return "", nil
instanceIDBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/instance-id")
if err != nil {
return "", fmt.Errorf("error reading instance-id from AWS metadata: %v", err)
}
instanceID := string(instanceIDBytes)
config := aws.NewConfig()
config = config.WithCredentialsChainVerboseErrors(true)
s, err := session.NewSession(config)
if err != nil {
return "", fmt.Errorf("error starting new AWS session: %v", err)
}
domain := domains[0]
klog.Infof("Using hostname from AWS metadata service: %s", domain)
svc := ec2.New(s, config.WithRegion(string(azBytes[:len(azBytes)-1])))
return domain, nil
result, err := svc.DescribeInstances(&ec2.DescribeInstancesInput{
InstanceIds: []*string{&instanceID},
})
if len(result.Reservations) != 1 {
return "", fmt.Errorf("Too many reservations returned for the single instance-id")
}
if len(result.Reservations[0].Instances) != 1 {
return "", fmt.Errorf("Too many instances returned for the single instance-id")
}
return *(result.Reservations[0].Instances[0].PrivateDnsName), nil
}
if k == "@digitalocean" {