support multiple ec2 ips in aws provider

This commit is contained in:
Jason Zhao 2017-08-03 15:57:59 -07:00
parent 04b2c29a5a
commit 43e606a5da
2 changed files with 85 additions and 27 deletions

View File

@ -50,6 +50,7 @@ import (
"k8s.io/kubernetes/pkg/controller"
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
"k8s.io/kubernetes/pkg/volume"
"path"
)
// ProviderName is the name of this cloud provider.
@ -976,11 +977,21 @@ func (c *Cloud) NodeAddresses(name types.NodeName) ([]v1.NodeAddress, error) {
if c.selfAWSInstance.nodeName == name || len(name) == 0 {
addresses := []v1.NodeAddress{}
internalIP, err := c.metadata.GetMetadata("local-ipv4")
macs, err := c.metadata.GetMetadata("network/interfaces/macs/")
if err != nil {
return nil, fmt.Errorf("error querying AWS metadata for %q: %q", "local-ipv4", err)
return nil, fmt.Errorf("error querying AWS metadata for %q: %q", "network/interfaces/macs", err)
}
for _, macID := range strings.Split(macs, "\n") {
macPath := path.Join("network/interfaces/macs/", macID, "local-ipv4s")
internalIPs, err := c.metadata.GetMetadata(macPath)
if err != nil {
return nil, fmt.Errorf("error querying AWS metadata for %q: %q", macPath, err)
}
for _, internalIP := range strings.Split(internalIPs, "\n") {
addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: internalIP})
}
}
addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: internalIP})
externalIP, err := c.metadata.GetMetadata("public-ipv4")
if err != nil {
@ -1029,13 +1040,24 @@ func extractNodeAddresses(instance *ec2.Instance) ([]v1.NodeAddress, error) {
addresses := []v1.NodeAddress{}
privateIPAddress := aws.StringValue(instance.PrivateIpAddress)
if privateIPAddress != "" {
ip := net.ParseIP(privateIPAddress)
if ip == nil {
return nil, fmt.Errorf("EC2 instance had invalid private address: %s (%s)", aws.StringValue(instance.InstanceId), privateIPAddress)
// handle internal network interfaces
for _, networkInterface := range instance.NetworkInterfaces {
// skip network interfaces that are not currently in use
if isNilOrEmpty(networkInterface.Status) || *networkInterface.Status != ec2.NetworkInterfaceStatusInUse {
continue
}
for _, internalIP := range networkInterface.PrivateIpAddresses {
if !isNilOrEmpty(internalIP.PrivateIpAddress) {
ipAddress := *internalIP.PrivateIpAddress
ip := net.ParseIP(ipAddress)
if ip == nil {
return nil, fmt.Errorf("EC2 instance had invalid private address: %s (%s)", orEmpty(instance.InstanceId), ipAddress)
}
addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: ip.String()})
}
}
addresses = append(addresses, v1.NodeAddress{Type: v1.NodeInternalIP, Address: ip.String()})
}
// TODO: Other IP addresses (multiple ips)?

View File

@ -113,16 +113,17 @@ func TestReadAWSCloudConfig(t *testing.T) {
}
type FakeAWSServices struct {
region string
instances []*ec2.Instance
selfInstance *ec2.Instance
networkInterfacesMacs []string
networkInterfacesVpcIDs []string
region string
instances []*ec2.Instance
selfInstance *ec2.Instance
networkInterfacesMacs []string
networkInterfacesPrivateIPs [][]string
networkInterfacesVpcIDs []string
ec2 *FakeEC2
elb *FakeELB
asg *FakeASG
metadata *FakeMetadata
ec2 *FakeEC2
elb *FakeELB
asg *FakeASG
metadata *FakeMetadata
}
func NewFakeAWSServices() *FakeAWSServices {
@ -359,6 +360,13 @@ func (self *FakeMetadata) GetMetadata(key string) (string, error) {
}
}
}
if len(keySplit) == 5 && keySplit[4] == "local-ipv4s" {
for i, macElem := range self.aws.networkInterfacesMacs {
if macParam == macElem {
return strings.Join(self.aws.networkInterfacesPrivateIPs[i], "/\n"), nil
}
}
}
return "", nil
}
} else {
@ -553,6 +561,16 @@ func TestNodeAddresses(t *testing.T) {
instance0.PrivateIpAddress = aws.String("192.168.0.1")
instance0.PublicDnsName = aws.String("instance-same.ec2.external")
instance0.PublicIpAddress = aws.String("1.2.3.4")
instance0.NetworkInterfaces = []*ec2.InstanceNetworkInterface{
{
Status: aws.String(ec2.NetworkInterfaceStatusInUse),
PrivateIpAddresses: []*ec2.InstancePrivateIpAddress{
{
PrivateIpAddress: aws.String("192.168.0.1"),
},
},
},
}
instance0.InstanceType = aws.String("c3.large")
instance0.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
state0 := ec2.InstanceState{
@ -598,6 +616,8 @@ func TestNodeAddresses(t *testing.T) {
}
aws3, _ := mockInstancesResp(&instance0, instances[0:1])
// change node name so it uses the instance instead of metadata
aws3.selfAWSInstance.nodeName = "foo"
addrs3, err3 := aws3.NodeAddresses("instance-same.ec2.internal")
if err3 != nil {
t.Errorf("Should not error when instance found")
@ -609,18 +629,34 @@ func TestNodeAddresses(t *testing.T) {
testHasNodeAddress(t, addrs3, v1.NodeExternalIP, "1.2.3.4")
testHasNodeAddress(t, addrs3, v1.NodeExternalDNS, "instance-same.ec2.external")
testHasNodeAddress(t, addrs3, v1.NodeInternalDNS, "instance-same.ec2.internal")
}
// Fetch from metadata
aws4, fakeServices := mockInstancesResp(&instance0, []*ec2.Instance{&instance0})
fakeServices.selfInstance.PublicIpAddress = aws.String("2.3.4.5")
fakeServices.selfInstance.PrivateIpAddress = aws.String("192.168.0.2")
func TestNodeAddressesWithMetadata(t *testing.T) {
var instance ec2.Instance
addrs4, err4 := aws4.NodeAddresses(mapInstanceToNodeName(&instance0))
if err4 != nil {
t.Errorf("unexpected error: %v", err4)
instanceName := "instance.ec2.internal"
instance.InstanceId = aws.String("i-0")
instance.PrivateDnsName = &instanceName
instance.PublicIpAddress = aws.String("2.3.4.5")
instance.InstanceType = aws.String("c3.large")
instance.Placement = &ec2.Placement{AvailabilityZone: aws.String("us-east-1a")}
state := ec2.InstanceState{
Name: aws.String("running"),
}
testHasNodeAddress(t, addrs4, v1.NodeInternalIP, "192.168.0.2")
testHasNodeAddress(t, addrs4, v1.NodeExternalIP, "2.3.4.5")
instance.State = &state
instances := []*ec2.Instance{&instance}
awsCloud, awsServices := mockInstancesResp(&instance, instances)
awsServices.networkInterfacesMacs = []string{ "0a:26:89:f3:9c:f6", "0a:77:64:c4:6a:48" ,}
awsServices.networkInterfacesPrivateIPs = [][]string{ []string{"192.168.0.1"}, []string{"192.168.0.2"} ,}
addrs, err := awsCloud.NodeAddresses("")
if err != nil {
t.Errorf("unexpected error: %v", err)
}
testHasNodeAddress(t, addrs, v1.NodeInternalIP, "192.168.0.1")
testHasNodeAddress(t, addrs, v1.NodeInternalIP, "192.168.0.2")
testHasNodeAddress(t, addrs, v1.NodeExternalIP, "2.3.4.5")
}
func TestGetRegion(t *testing.T) {