Reduce API calls for Azure instance metadata

This commit is contained in:
Pengfei Ni 2018-08-16 14:38:04 +08:00
parent 76e9fdaa72
commit a09bcb20c7
3 changed files with 49 additions and 24 deletions

View File

@ -59,6 +59,13 @@ type InstanceMetadata struct {
baseURL string baseURL string
} }
// ComputeMetadata represents compute information
type ComputeMetadata struct {
Name string `json:"name,omitempty"`
Zone string `json:"zone,omitempty"`
VMSize string `json:"vmSize,omitempty"`
}
// NewInstanceMetadata creates an instance of the InstanceMetadata accessor object. // NewInstanceMetadata creates an instance of the InstanceMetadata accessor object.
func NewInstanceMetadata() *InstanceMetadata { func NewInstanceMetadata() *InstanceMetadata {
return &InstanceMetadata{ return &InstanceMetadata{

View File

@ -51,7 +51,12 @@ func (az *Cloud) NodeAddresses(ctx context.Context, name types.NodeName) ([]v1.N
} }
if az.UseInstanceMetadata { if az.UseInstanceMetadata {
isLocalInstance, err := az.isCurrentInstance(name) computeMetadata, err := az.getComputeMetadata()
if err != nil {
return nil, err
}
isLocalInstance, err := az.isCurrentInstance(name, computeMetadata.Name)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -119,23 +124,30 @@ func (az *Cloud) InstanceShutdownByProviderID(ctx context.Context, providerID st
return false, cloudprovider.NotImplemented return false, cloudprovider.NotImplemented
} }
func (az *Cloud) isCurrentInstance(name types.NodeName) (bool, error) { // getComputeMetadata gets compute information from instance metadata.
nodeName := mapNodeNameToVMName(name) func (az *Cloud) getComputeMetadata() (*ComputeMetadata, error) {
metadataName, err := az.metadata.Text("instance/compute/name") computeInfo := ComputeMetadata{}
err := az.metadata.Object(computeMetadataURI, &computeInfo)
if err != nil { if err != nil {
return false, err return nil, err
} }
return &computeInfo, nil
}
func (az *Cloud) isCurrentInstance(name types.NodeName, metadataVMName string) (bool, error) {
var err error
nodeName := mapNodeNameToVMName(name)
if az.VMType == vmTypeVMSS { if az.VMType == vmTypeVMSS {
// VMSS vmName is not same with hostname, use hostname instead. // VMSS vmName is not same with hostname, use hostname instead.
metadataName, err = os.Hostname() metadataVMName, err = os.Hostname()
if err != nil { if err != nil {
return false, err return false, err
} }
} }
metadataName = strings.ToLower(metadataName) metadataVMName = strings.ToLower(metadataVMName)
return (metadataName == nodeName), err return (metadataVMName == nodeName), err
} }
// InstanceID returns the cloud provider ID of the specified instance. // InstanceID returns the cloud provider ID of the specified instance.
@ -144,7 +156,12 @@ func (az *Cloud) InstanceID(ctx context.Context, name types.NodeName) (string, e
nodeName := mapNodeNameToVMName(name) nodeName := mapNodeNameToVMName(name)
if az.UseInstanceMetadata { if az.UseInstanceMetadata {
isLocalInstance, err := az.isCurrentInstance(name) computeMetadata, err := az.getComputeMetadata()
if err != nil {
return "", err
}
isLocalInstance, err := az.isCurrentInstance(name, computeMetadata.Name)
if err != nil { if err != nil {
return "", err return "", err
} }
@ -160,11 +177,7 @@ func (az *Cloud) InstanceID(ctx context.Context, name types.NodeName) (string, e
} }
// Get scale set name and instanceID from vmName for vmss. // Get scale set name and instanceID from vmName for vmss.
metadataName, err := az.metadata.Text("instance/compute/name") ssName, instanceID, err := extractVmssVMName(computeMetadata.Name)
if err != nil {
return "", err
}
ssName, instanceID, err := extractVmssVMName(metadataName)
if err != nil { if err != nil {
if err == ErrorNotVmssInstance { if err == ErrorNotVmssInstance {
// Compose machineID for standard Node. // Compose machineID for standard Node.
@ -197,14 +210,18 @@ func (az *Cloud) InstanceTypeByProviderID(ctx context.Context, providerID string
// Adding node label from cloud provider: beta.kubernetes.io/instance-type=[value] // Adding node label from cloud provider: beta.kubernetes.io/instance-type=[value]
func (az *Cloud) InstanceType(ctx context.Context, name types.NodeName) (string, error) { func (az *Cloud) InstanceType(ctx context.Context, name types.NodeName) (string, error) {
if az.UseInstanceMetadata { if az.UseInstanceMetadata {
isLocalInstance, err := az.isCurrentInstance(name) computeMetadata, err := az.getComputeMetadata()
if err != nil {
return "", err
}
isLocalInstance, err := az.isCurrentInstance(name, computeMetadata.Name)
if err != nil { if err != nil {
return "", err return "", err
} }
if isLocalInstance { if isLocalInstance {
machineType, err := az.metadata.Text("instance/compute/vmSize") if computeMetadata.VMSize != "" {
if err == nil { return computeMetadata.VMSize, nil
return machineType, nil
} }
} }
} }

View File

@ -29,8 +29,8 @@ import (
) )
const ( const (
faultDomainURI = "v1/InstanceInfo/FD" faultDomainURI = "v1/InstanceInfo/FD"
zoneMetadataURI = "instance/compute/zone" computeMetadataURI = "instance/compute"
) )
var faultMutex = &sync.Mutex{} var faultMutex = &sync.Mutex{}
@ -58,19 +58,20 @@ func (az *Cloud) GetZoneID(zoneLabel string) string {
// GetZone returns the Zone containing the current availability zone and locality region that the program is running in. // GetZone returns the Zone containing the current availability zone and locality region that the program is running in.
// If the node is not running with availability zones, then it will fall back to fault domain. // If the node is not running with availability zones, then it will fall back to fault domain.
func (az *Cloud) GetZone(ctx context.Context) (cloudprovider.Zone, error) { func (az *Cloud) GetZone(ctx context.Context) (cloudprovider.Zone, error) {
zone, err := az.metadata.Text(zoneMetadataURI) computeInfo := ComputeMetadata{}
err := az.metadata.Object(computeMetadataURI, &computeInfo)
if err != nil { if err != nil {
return cloudprovider.Zone{}, err return cloudprovider.Zone{}, err
} }
if zone == "" { if computeInfo.Zone == "" {
glog.V(3).Infof("Availability zone is not enabled for the node, falling back to fault domain") glog.V(3).Infof("Availability zone is not enabled for the node, falling back to fault domain")
return az.getZoneFromFaultDomain() return az.getZoneFromFaultDomain()
} }
zoneID, err := strconv.Atoi(zone) zoneID, err := strconv.Atoi(computeInfo.Zone)
if err != nil { if err != nil {
return cloudprovider.Zone{}, fmt.Errorf("failed to parse zone ID %q: %v", zone, err) return cloudprovider.Zone{}, fmt.Errorf("failed to parse zone ID %q: %v", computeInfo.Zone, err)
} }
return cloudprovider.Zone{ return cloudprovider.Zone{