Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use PrivateDnsName as Node name in nodeadm #1715

Merged
merged 1 commit into from
Mar 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 11 additions & 56 deletions nodeadm/cmd/nodeadm/init/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@ package init

import (
"context"
"encoding/base64"
"fmt"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/config"
"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go/service/eks"
"github.com/aws/aws-sdk-go-v2/service/ec2"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thank you for the -28k lines 😂

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's the least I could do ☺️

"github.com/integrii/flaggy"
"go.uber.org/zap"
"k8s.io/utils/strings/slices"
Expand Down Expand Up @@ -145,7 +145,14 @@ func (c *initCmd) Run(log *zap.Logger, opts *cli.GlobalOptions) error {
// perform in-place updates when allowed by the user
func enrichConfig(log *zap.Logger, cfg *api.NodeConfig) error {
log.Info("Fetching instance details..")
instanceDetails, err := api.GetIMDSInstanceDetails(context.TODO(), imds.New(imds.Options{}))
imdsClient := imds.New(imds.Options{})
awsConfig, err := config.LoadDefaultConfig(context.TODO(), config.WithClientLogMode(aws.LogRetries), config.WithEC2IMDSRegion(func(o *config.UseEC2IMDSRegion) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah! thanks for the fix. 💚

o.Client = imdsClient
}))
if err != nil {
return err
}
instanceDetails, err := api.GetInstanceDetails(context.TODO(), imdsClient, ec2.NewFromConfig(awsConfig))
if err != nil {
return err
}
Expand All @@ -162,55 +169,3 @@ func enrichConfig(log *zap.Logger, cfg *api.NodeConfig) error {
log.Info("Default options populated", zap.Reflect("defaults", cfg.Status.Defaults))
return nil
}

// Discovers all cluster details using a describe call to the eks endpoint and
// updates the value of the config's `ClusterDetails` in-place
func populateClusterDetails(eksClient *eks.EKS, clusterName string, cfg *api.NodeConfig) error {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was unused and we've decided to require these args in the user data.

if err := eksClient.WaitUntilClusterActive(&eks.DescribeClusterInput{Name: &clusterName}); err != nil {
return err
}
describeResponse, err := eksClient.DescribeCluster(&eks.DescribeClusterInput{Name: &clusterName})
if err != nil {
return err
}

ipFamily := *describeResponse.Cluster.KubernetesNetworkConfig.IpFamily

var cidr string
if ipFamily == eks.IpFamilyIpv4 {
cidr = *describeResponse.Cluster.KubernetesNetworkConfig.ServiceIpv4Cidr
} else if ipFamily == eks.IpFamilyIpv6 {
cidr = *describeResponse.Cluster.KubernetesNetworkConfig.ServiceIpv6Cidr
} else {
return fmt.Errorf("bad ipFamily: %s", ipFamily)
}

isOutpost := false
clusterId := cfg.Spec.Cluster.ID
// detect whether the cluster is an aws outpost cluster depending on whether
// the response contains the outpost ID
if outpostId := describeResponse.Cluster.Id; outpostId != nil {
clusterId = *outpostId
isOutpost = true
}

enableOutpost := isOutpost
// respect the user override for enabling the outpost
if enabled := cfg.Spec.Cluster.EnableOutpost; enabled != nil {
enableOutpost = *enabled
}

caCert, err := base64.StdEncoding.DecodeString(*describeResponse.Cluster.CertificateAuthority.Data)
if err != nil {
return err
}

cfg.Spec.Cluster.Name = *describeResponse.Cluster.Name
cfg.Spec.Cluster.APIServerEndpoint = *describeResponse.Cluster.Endpoint
cfg.Spec.Cluster.CertificateAuthority = caCert
cfg.Spec.Cluster.CIDR = cidr
cfg.Spec.Cluster.EnableOutpost = &enableOutpost
cfg.Spec.Cluster.ID = clusterId

return nil
}
4 changes: 2 additions & 2 deletions nodeadm/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ require (
require dario.cat/mergo v1.0.0 // direct

require (
github.com/aws/aws-sdk-go-v2 v1.24.1 // indirect
github.com/aws/aws-sdk-go-v2 v1.24.1
github.com/aws/aws-sdk-go-v2/credentials v1.16.16 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.2.10 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.5.10 // indirect
Expand All @@ -54,7 +54,7 @@ require (
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/jmespath/go-jmespath v0.4.0
github.com/json-iterator/go v1.1.12 // indirect
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
Expand Down
32 changes: 0 additions & 32 deletions nodeadm/internal/api/net.go
Original file line number Diff line number Diff line change
@@ -1,43 +1,11 @@
package api

import (
"context"
"fmt"
"io"
"net"
"strings"

"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
)

// Fetch information about the ec2 instance using IMDS data.
// This information is stored into the internal config to avoid redundant calls
// to IMDS when looking for instance metadata
func GetIMDSInstanceDetails(ctx context.Context, imdsClient *imds.Client) (*InstanceDetails, error) {
instanceIdenitityDocument, err := imdsClient.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{})
if err != nil {
return nil, err
}

macResponse, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{Path: "mac"})
if err != nil {
return nil, err
}
mac, err := io.ReadAll(macResponse.Content)
if err != nil {
return nil, err
}

instanceDetails := InstanceDetails{
ID: instanceIdenitityDocument.InstanceID,
Region: instanceIdenitityDocument.Region,
Type: instanceIdenitityDocument.InstanceType,
AvailabilityZone: instanceIdenitityDocument.AvailabilityZone,
MAC: string(mac),
}
return &instanceDetails, nil
}

// Derive the default ClusterIP of the kube-dns service from EKS built-in CoreDNS addon
func (details *ClusterDetails) GetClusterDns() (string, error) {
ipFamily, err := GetCIDRIpFamily(details.CIDR)
Expand Down
68 changes: 68 additions & 0 deletions nodeadm/internal/api/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
package api

import (
"context"
"fmt"
"io"
"time"

"github.com/aws/aws-sdk-go-v2/feature/ec2/imds"
"github.com/aws/aws-sdk-go-v2/service/ec2"
"github.com/aws/aws-sdk-go/aws"
ec2extra "github.com/awslabs/amazon-eks-ami/nodeadm/internal/aws/ec2"
)

// Fetch information about the ec2 instance using IMDS data.
// This information is stored into the internal config to avoid redundant calls
// to IMDS when looking for instance metadata
func GetInstanceDetails(ctx context.Context, imdsClient *imds.Client, ec2Client *ec2.Client) (*InstanceDetails, error) {
instanceIdenitityDocument, err := imdsClient.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{})
if err != nil {
return nil, err
}

macResponse, err := imdsClient.GetMetadata(ctx, &imds.GetMetadataInput{Path: "mac"})
if err != nil {
return nil, err
}
mac, err := io.ReadAll(macResponse.Content)
if err != nil {
return nil, err
}

privateDNSName, err := getPrivateDNSName(ec2Client, instanceIdenitityDocument.InstanceID)
cartermckinnon marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

return &InstanceDetails{
ID: instanceIdenitityDocument.InstanceID,
Region: instanceIdenitityDocument.Region,
Type: instanceIdenitityDocument.InstanceType,
AvailabilityZone: instanceIdenitityDocument.AvailabilityZone,
MAC: string(mac),
PrivateDNSName: privateDNSName,
}, nil
}

const privateDNSNameAvailableTimeout = 3 * time.Minute

// GetPrivateDNSName returns this instance's private DNS name as reported by the EC2 API, waiting until it's available if necessary.
func getPrivateDNSName(ec2Client *ec2.Client, instanceID string) (string, error) {
w := ec2extra.NewInstanceConditionWaiter(ec2Client, privateDNSNameAvailable, func(opts *ec2extra.InstanceConditionWaiterOptions) {
opts.LogWaitAttempts = true
})
out, err := w.WaitForOutput(context.TODO(), &ec2.DescribeInstancesInput{InstanceIds: []string{instanceID}}, privateDNSNameAvailableTimeout)
if err != nil {
return "", err
}
privateDNSName := aws.StringValue(out.Reservations[0].Instances[0].PrivateDnsName)
return privateDNSName, nil
}

func privateDNSNameAvailable(out *ec2.DescribeInstancesOutput) (bool, error) {
if out == nil || len(out.Reservations) != 1 || len(out.Reservations[0].Instances) != 1 {
return false, fmt.Errorf("reservation or instance not found")
}
return aws.StringValue(out.Reservations[0].Instances[0].PrivateDnsName) != "", nil
}
1 change: 1 addition & 0 deletions nodeadm/internal/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type InstanceDetails struct {
Type string `json:"type,omitempty"`
AvailabilityZone string `json:"availabilityZone,omitempty"`
MAC string `json:"mac,omitempty"`
PrivateDNSName string `json:"privateDnsName,omitempty"`
}

type DefaultOptions struct {
Expand Down
Loading
Loading