Merge pull request #12862 from johngmyers/instanceid-nodename

Use instance ID as node name when AWS CCM supports it
This commit is contained in:
Kubernetes Prow Robot 2021-12-05 14:58:32 -08:00 committed by GitHub
commit f7e66049d6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 41 additions and 17 deletions

View File

@ -55,6 +55,9 @@ type ServerOptions struct {
SigningCAs []string `json:"signingCAs"`
// CertNames is the list of active certificate names.
CertNames []string `json:"certNames"`
// UseInstanceIDForNodeName uses the instance ID instead of the hostname for the node name.
UseInstanceIDForNodeName bool `json:"useInstanceIDForNodeName,omitempty"`
}
type ServerProviderOptions struct {

View File

@ -109,7 +109,7 @@ func (s *Server) bootstrap(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
id, err := s.verifier.VerifyToken(ctx, r.Header.Get("Authorization"), body)
id, err := s.verifier.VerifyToken(ctx, r.Header.Get("Authorization"), body, s.opt.Server.UseInstanceIDForNodeName)
if err != nil {
klog.Infof("bootstrap %s verify err: %v", r.RemoteAddr, err)
w.WriteHeader(http.StatusForbidden)

View File

@ -8,6 +8,9 @@ This is a document to gather the release notes prior to the release.
## Other significant changes
* If the Kubernetes version is 1.23 or later and the external AWS Cloud Controller Manager is
being used, then Kubernetes Node resources will be named after their AWS instance ID instead of their domain name.
# Breaking changes
* Support for Kubernetes version 1.17 has been removed.

View File

@ -619,5 +619,6 @@ func (b *KubeletBuilder) kubeletNames() ([]string, error) {
return nil, fmt.Errorf("error describing instances: %v", err)
}
return awsup.GetInstanceCertificateNames(result)
useInstanceIDForNodeName := b.Cluster.Spec.ExternalCloudControllerManager != nil && b.IsKubernetesGTE("1.23")
return awsup.GetInstanceCertificateNames(result, useInstanceIDForNodeName)
}

View File

@ -78,6 +78,8 @@ type Config struct {
APIServerConfig *APIServerConfig `json:",omitempty"`
// NvidiaGPU contains the configuration for nvidia
NvidiaGPU *kops.NvidiaGPUConfig `json:",omitempty"`
// UseInstanceIDForNodeName uses the instance ID instead of the hostname for the node name.
UseInstanceIDForNodeName bool `json:"useInstanceIDForNodeName,omitempty"`
}
// BootConfig is the configuration for the nodeup binary that might be too big to fit in userdata.
@ -206,6 +208,10 @@ func NewConfig(cluster *kops.Cluster, instanceGroup *kops.InstanceGroup) (*Confi
config.DefaultMachineType = fi.String(strings.Split(instanceGroup.Spec.MachineType, ",")[0])
}
if cluster.Spec.ExternalCloudControllerManager != nil && cluster.IsKubernetesGTE("1.23") && cluster.Spec.CloudProvider == string(kops.CloudProviderAWS) {
config.UseInstanceIDForNodeName = true
}
return &config, &bootConfig
}

View File

@ -39,5 +39,5 @@ type VerifyResult struct {
// Verifier verifies authentication credentials for requests.
type Verifier interface {
VerifyToken(ctx context.Context, token string, body []byte) (*VerifyResult, error)
VerifyToken(ctx context.Context, token string, body []byte, useInstanceIDForNodeName bool) (*VerifyResult, error)
}

View File

@ -2071,8 +2071,8 @@ func GetRolesInInstanceProfile(c AWSCloud, profileName string) ([]string, error)
}
// GetInstanceCertificateNames returns the instance hostname and addresses that should go into certificates.
// The first value is the node name and any additional values are IP addresses.
func GetInstanceCertificateNames(instances *ec2.DescribeInstancesOutput) (addrs []string, err error) {
// The first value is the node name and any additional values are the DNS name and IP addresses.
func GetInstanceCertificateNames(instances *ec2.DescribeInstancesOutput, useInstanceIDForNodeName bool) (addrs []string, err error) {
if len(instances.Reservations) != 1 {
return nil, fmt.Errorf("too many reservations returned for the single instance-id")
}
@ -2083,9 +2083,11 @@ func GetInstanceCertificateNames(instances *ec2.DescribeInstancesOutput) (addrs
instance := instances.Reservations[0].Instances[0]
name := *instance.PrivateDnsName
if useInstanceIDForNodeName {
addrs = append(addrs, *instance.InstanceId)
}
addrs = append(addrs, name)
addrs = append(addrs, *instance.PrivateDnsName)
// We only use data for the first interface, and only the first IP
for _, iface := range instance.NetworkInterfaces {

View File

@ -120,7 +120,7 @@ type ResponseMetadata struct {
RequestId string `xml:"RequestId"`
}
func (a awsVerifier) VerifyToken(ctx context.Context, token string, body []byte) (*bootstrap.VerifyResult, error) {
func (a awsVerifier) VerifyToken(ctx context.Context, token string, body []byte, useInstanceIDForNodeName bool) (*bootstrap.VerifyResult, error) {
if !strings.HasPrefix(token, AWSAuthenticationTokenPrefix) {
return nil, fmt.Errorf("incorrect authorization type")
}
@ -232,7 +232,7 @@ func (a awsVerifier) VerifyToken(ctx context.Context, token string, body []byte)
instance := instances.Reservations[0].Instances[0]
addrs, err := GetInstanceCertificateNames(instances)
addrs, err := GetInstanceCertificateNames(instances, useInstanceIDForNodeName)
if err != nil {
return nil, err
}

View File

@ -64,7 +64,7 @@ func NewTPMVerifier(opt *gcetpm.TPMVerifierOptions) (bootstrap.Verifier, error)
var _ bootstrap.Verifier = &tpmVerifier{}
func (v *tpmVerifier) VerifyToken(ctx context.Context, authToken string, body []byte) (*bootstrap.VerifyResult, error) {
func (v *tpmVerifier) VerifyToken(ctx context.Context, authToken string, body []byte, useInstanceIDForNodeName bool) (*bootstrap.VerifyResult, error) {
// Reminder: we shouldn't trust any data we get from the client until we've checked the signature (and even then...)
// Thankfully the GCE SDK does seem to escape the parameters correctly, for example.

View File

@ -585,6 +585,10 @@ func (tf *TemplateFunctions) KopsControllerConfig() (string, error) {
Region: tf.Region,
}
if cluster.Spec.ExternalCloudControllerManager != nil && cluster.IsKubernetesGTE("1.23") {
config.Server.UseInstanceIDForNodeName = true
}
case kops.CloudProviderGCE:
c := tf.cloud.(gce.GCECloud)
@ -599,7 +603,7 @@ func (tf *TemplateFunctions) KopsControllerConfig() (string, error) {
}
}
if tf.Cluster.Spec.IsKopsControllerIPAM() {
if cluster.Spec.IsKopsControllerIPAM() {
config.EnableCloudIPAM = true
}

View File

@ -450,7 +450,7 @@ func completeWarmingLifecycleAction(cloud awsup.AWSCloud, modelContext *model.No
}
func evaluateSpec(c *NodeUpCommand, nodeupConfig *nodeup.Config) error {
hostnameOverride, err := evaluateHostnameOverride(api.CloudProviderID(c.cluster.Spec.CloudProvider))
hostnameOverride, err := evaluateHostnameOverride(api.CloudProviderID(c.cluster.Spec.CloudProvider), nodeupConfig.UseInstanceIDForNodeName)
if err != nil {
return err
}
@ -480,14 +480,19 @@ func evaluateSpec(c *NodeUpCommand, nodeupConfig *nodeup.Config) error {
return nil
}
func evaluateHostnameOverride(cloudProvider api.CloudProviderID) (string, error) {
func evaluateHostnameOverride(cloudProvider api.CloudProviderID, useInstanceIDForNodeName bool) (string, error) {
switch cloudProvider {
case api.CloudProviderAWS:
hostnameBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/local-hostname")
if err != nil {
return "", fmt.Errorf("error reading local-hostname from AWS metadata: %v", err)
source := "local-hostname"
if useInstanceIDForNodeName {
source = "instance-id"
}
return string(hostnameBytes), nil
nodeNameBytes, err := vfs.Context.ReadFile("metadata://aws/meta-data/" + source)
if err != nil {
return "", fmt.Errorf("error reading %s from AWS metadata: %v", source, err)
}
return string(nodeNameBytes), nil
case api.CloudProviderGCE:
// This lets us tolerate broken hostnames (i.e. systemd)
b, err := vfs.Context.ReadFile("metadata://gce/instance/hostname")