Skip to content

Commit

Permalink
Support attaching a public IP on master boot
Browse files Browse the repository at this point in the history
  • Loading branch information
justinsb committed Nov 9, 2015
1 parent 49d6488 commit 052cefe
Show file tree
Hide file tree
Showing 4 changed files with 78 additions and 4 deletions.
25 changes: 22 additions & 3 deletions pkg/bootstrap/bootstrapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,14 @@ package bootstrap
import (
"encoding/json"
"fmt"
"github.com/golang/glog"
"io/ioutil"
"os"
"strings"

"github.com/golang/glog"
"k8s.io/kubernetes/pkg/cloudprovider"
"k8s.io/kubernetes/pkg/util/exec"
"k8s.io/kubernetes/pkg/util/mount"
"os"
"strings"
)

// Bootstrapper is the main bootstrapping manager class
Expand Down Expand Up @@ -54,11 +55,17 @@ func (b *Bootstrapper) RunOnce() error {
return fmt.Errorf("unable to build cloud provider: %v", err)
}

// The master volume acts as a mutex, so we always mount it first
err = b.mountMasterVolume()
if err != nil {
return fmt.Errorf("unable to mount master volume: %v", err)
}

err = b.configureMasterPublicIP()
if err != nil {
return fmt.Errorf("unable to associate master IP: %v", err)
}

err = b.configureMasterRoute()
if err != nil {
return fmt.Errorf("unable to configure master route: %v", err)
Expand Down Expand Up @@ -102,6 +109,18 @@ func (b *Bootstrapper) buildCloudProvider() error {
return nil
}

func (b *Bootstrapper) configureMasterPublicIP() error {
ip := b.config.MasterPublicIP

err := b.masterBootstrap.AttachPublicIP(ip)
if err != nil {
// TODO: This is retryable
return fmt.Errorf("error attaching public IP (%s): %v", ip, err)
}

return nil
}

func (b *Bootstrapper) mountMasterVolume() error {
// We could discover the volume using metadata (at least on AWS),
// but it is probably easier just to rely on it being present in config
Expand Down
3 changes: 2 additions & 1 deletion pkg/bootstrap/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ type Configuration struct {
CloudProvider string
CloudProviderConfig string

MasterCIDR string
MasterPublicIP string
MasterCIDR string

ClusterID string

Expand Down
3 changes: 3 additions & 0 deletions pkg/cloudprovider/cloud.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,4 +166,7 @@ type MasterBootstrap interface {
// The volume id will typically be an ID for the default volume type for that cloud,
// but is an opaque token typically provided to the bootstrapper in a config file.
AttachMasterVolume(volumeID string) (string, error)

// Attaches the specified public IP to the master
AttachPublicIP(ip string) error
}
51 changes: 51 additions & 0 deletions pkg/cloudprovider/providers/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,9 @@ type EC2 interface {
DeleteRoute(request *ec2.DeleteRouteInput) (*ec2.DeleteRouteOutput, error)

ModifyInstanceAttribute(request *ec2.ModifyInstanceAttributeInput) (*ec2.ModifyInstanceAttributeOutput, error)

DescribeAddresses(*ec2.DescribeAddressesInput) ([]*ec2.Address, error)
AssociateAddress(*ec2.AssociateAddressInput) (*ec2.AssociateAddressOutput, error)
}

// This is a simple pass-through of the ELB client interface, which allows for testing
Expand Down Expand Up @@ -443,6 +446,19 @@ func (s *awsSdkEC2) ModifyInstanceAttribute(request *ec2.ModifyInstanceAttribute
return s.ec2.ModifyInstanceAttribute(request)
}

func (s *awsSdkEC2) DescribeAddresses(request *ec2.DescribeAddressesInput) ([]*ec2.Address, error) {
// Not paged
response, err := s.ec2.DescribeAddresses(request)
if err != nil {
return nil, fmt.Errorf("error listing AWS addresses: %v", err)
}
return response.Addresses, nil
}

func (s *awsSdkEC2) AssociateAddress(request *ec2.AssociateAddressInput) (*ec2.AssociateAddressOutput, error) {
return s.ec2.AssociateAddress(request)
}

func init() {
cloudprovider.RegisterCloudProvider(ProviderName, func(config io.Reader) (cloudprovider.Interface, error) {
creds := credentials.NewChainCredentials(
Expand Down Expand Up @@ -1209,6 +1225,41 @@ func (c *AWSCloud) AttachMasterVolume(volumeID string) (string, error) {
return c.attachVolumeAt(awsInstance, disk, mountDevice, alreadyAttached)
}

// Implements MasterBootstrap.AttachPublicIP
func (c *AWSCloud) AttachPublicIP(ip string) error {
instanceName := "" // self
awsInstance, err := c.getAwsInstance(instanceName)
if err != nil {
return err
}

addresses, err := c.ec2.DescribeAddresses(&ec2.DescribeAddressesInput{
PublicIps: []*string{aws.String(ip)},
})
if err != nil {
return err
}

if len(addresses) != 1 {
return fmt.Errorf("unexpectedly found multiple public addresses matching IP: %q", ip)
}

request := &ec2.AssociateAddressInput{
AllocationId: addresses[0].AllocationId,
AllowReassociation: aws.Bool(false), // Seems safer
InstanceId: &awsInstance.awsID,
}

response, err := c.ec2.AssociateAddress(request)
if err != nil {
return fmt.Errorf("error associating public IP %q with instance %q: %v", ip, awsInstance.awsID, err)
}

glog.V(2).Info("associated public IP %q with instance %q, reservation id=%q", ip, awsInstance.awsID, aws.StringValue(response.AssociationId))

return nil
}

// Implements Volumes.DetachDisk
func (aws *AWSCloud) DetachDisk(instanceName string, diskName string) (string, error) {
disk, err := newAWSDisk(aws, diskName)
Expand Down

1 comment on commit 052cefe

@k8s-teamcity-mesosphere

Choose a reason for hiding this comment

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

TeamCity OSS :: Kubernetes Mesos :: 4 - Smoke Tests Build 4122 outcome was SUCCESS
Summary: Tests passed: 1, ignored: 197 Build time: 00:10:09

Please sign in to comment.