kops/pkg/model/network.go

188 lines
4.8 KiB
Go

package model
import (
"fmt"
"k8s.io/kops/pkg/apis/kops"
"k8s.io/kops/upup/pkg/fi"
"k8s.io/kops/upup/pkg/fi/cloudup/awstasks"
"k8s.io/kubernetes/pkg/util/sets"
)
// NetworkModelBuilder configures network objects
type NetworkModelBuilder struct {
*KopsModelContext
}
var _ fi.ModelBuilder = &NetworkModelBuilder{}
func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error {
sharedVPC := b.Cluster.SharedVPC()
// VPC that holds everything for the cluster
{
t := &awstasks.VPC{
Name: s(b.ClusterName()),
EnableDNSHostnames: fi.Bool(true),
EnableDNSSupport: fi.Bool(true),
Shared: fi.Bool(sharedVPC),
}
if b.Cluster.Spec.NetworkID != "" {
t.ID = s(b.Cluster.Spec.NetworkID)
}
if b.Cluster.Spec.NetworkCIDR != "" {
t.CIDR = s(b.Cluster.Spec.NetworkCIDR)
}
c.AddTask(t)
}
if !sharedVPC {
dhcp := &awstasks.DHCPOptions{
Name: s(b.ClusterName()),
DomainNameServers: s("AmazonProvidedDNS"),
}
if b.Region == "us-east-1" {
dhcp.DomainName = s("ec2.internal")
} else {
dhcp.DomainName = s(b.Region + ".compute.internal")
}
c.AddTask(dhcp)
c.AddTask(&awstasks.VPCDHCPOptionsAssociation{
Name: s(b.ClusterName()),
VPC: b.LinkToVPC(),
DHCPOptions: dhcp,
})
} else {
// TODO: would be good to create these as shared, to verify them
}
// We always have a public route table, though for private networks it is only used for NGWs and ELBs
var publicRouteTable *awstasks.RouteTable
//if b.Cluster.IsTopologyPublic()
{
// The internet gateway is the main entry point to the cluster.
igw := &awstasks.InternetGateway{
Name: s(b.ClusterName()),
VPC: b.LinkToVPC(),
Shared: fi.Bool(sharedVPC),
}
c.AddTask(igw)
publicRouteTable = &awstasks.RouteTable{
Name: s(b.ClusterName()),
VPC: b.LinkToVPC(),
}
c.AddTask(publicRouteTable)
c.AddTask(&awstasks.Route{
Name: s("0.0.0.0/0"),
CIDR: s("0.0.0.0/0"),
RouteTable: publicRouteTable,
InternetGateway: igw,
})
}
privateZones := sets.NewString()
for i := range b.Cluster.Spec.Subnets {
subnetSpec := &b.Cluster.Spec.Subnets[i]
sharedSubnet := subnetSpec.ProviderID != ""
subnet := &awstasks.Subnet{
Name: s(subnetSpec.SubnetName + "." + b.ClusterName()),
VPC: b.LinkToVPC(),
AvailabilityZone: s(subnetSpec.Zone),
CIDR: s(subnetSpec.CIDR),
Shared: fi.Bool(sharedSubnet),
}
if subnetSpec.ProviderID != "" {
subnet.ID = s(subnetSpec.ProviderID)
}
c.AddTask(subnet)
switch subnetSpec.Type {
case kops.SubnetTypePublic, kops.SubnetTypeUtility:
if !sharedSubnet {
c.AddTask(&awstasks.RouteTableAssociation{
Name: s(subnetSpec.SubnetName + "." + b.ClusterName()),
RouteTable: publicRouteTable,
Subnet: subnet,
})
}
case kops.SubnetTypePrivate:
// Private subnets get a Network Gateway, and their own route table to associate them with the network gateway
if !sharedSubnet {
// Private Subnet Route Table Associations
//
// Map the Private subnet to the Private route table
c.AddTask(&awstasks.RouteTableAssociation{
Name: s("private-" + subnetSpec.SubnetName + "." + b.ClusterName()),
RouteTable: &awstasks.RouteTable{Name: s(b.NamePrivateRouteTableInZone(subnetSpec.Zone))},
Subnet: subnet,
})
privateZones.Insert(subnetSpec.Zone)
}
default:
return fmt.Errorf("subnet %q has unknown type %q", subnetSpec.SubnetName, subnetSpec.Type)
}
}
for _, zone := range privateZones.List() {
utilitySubnet, err := b.LinkToUtilitySubnetInZone(zone)
if err != nil {
return err
}
// Every NGW needs a public (Elastic) IP address, every private
// subnet needs a NGW, lets create it. We tie it to a subnet
// so we can track it in AWS
eip := &awstasks.ElasticIP{
Name: s(zone + "." + b.ClusterName()),
Subnet: utilitySubnet,
}
c.AddTask(eip)
// NAT Gateway
//
// All private subnets will need a NGW, one per zone
//
// The instances in the private subnet can access the Internet by
// using a network address translation (NAT) gateway that resides
// in the public subnet.
ngw := &awstasks.NatGateway{
Name: s(zone + "." + b.ClusterName()),
Subnet: utilitySubnet,
ElasticIp: eip,
}
c.AddTask(ngw)
// Private Route Table
//
// The private route table that will route to the NAT Gateway
rt := &awstasks.RouteTable{
Name: s(b.NamePrivateRouteTableInZone(zone)),
VPC: b.LinkToVPC(),
}
c.AddTask(rt)
// Private Routes
//
// Routes for the private route table.
// Will route to the NAT Gateway
c.AddTask(&awstasks.Route{
Name: s("private-" + zone + "-0.0.0.0/0"),
CIDR: s("0.0.0.0/0"),
RouteTable: rt,
NatGateway: ngw,
})
}
return nil
}