Skip to content

Commit

Permalink
PodCIDR, ServiceCIDR, ExternalCIDR, ReservedCIDRs as Networks
Browse files Browse the repository at this point in the history
  • Loading branch information
fra98 committed Dec 14, 2023
1 parent 3b367cc commit 239dba0
Show file tree
Hide file tree
Showing 24 changed files with 794 additions and 182 deletions.
10 changes: 7 additions & 3 deletions cmd/ipam/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ import (
"github.com/liqotech/liqo/pkg/consts"
liqoipam "github.com/liqotech/liqo/pkg/ipam"
"github.com/liqotech/liqo/pkg/leaderelection"
liqonetutils "github.com/liqotech/liqo/pkg/liqonet/utils"
flagsutils "github.com/liqotech/liqo/pkg/utils/flags"
"github.com/liqotech/liqo/pkg/utils/restcfg"
)
Expand Down Expand Up @@ -158,28 +157,33 @@ func initializeIPAM(ipam *liqoipam.IPAM, opts *liqoipam.Options, dynClient dynam
return fmt.Errorf("IPAM pointer is nil. Initialize it before calling this function")
}

if err := ipam.Init(liqoipam.Pools, dynClient, consts.IpamPort); err != nil {
if err := ipam.Init(liqoipam.Pools, dynClient); err != nil {
return err
}

// Configure PodCIDR
if err := ipam.SetPodCIDR(opts.PodCIDR.String()); err != nil {
return err
}

// Configure ServiceCIDR
if err := ipam.SetServiceCIDR(opts.ServiceCIDR.String()); err != nil {
return err
}

// Configure additional network pools.
for _, pool := range opts.AdditionalPools.StringList.StringList {
if err := ipam.AddNetworkPool(pool); err != nil {
return err
}
}

// Configure reserved subnets.
if err := ipam.SetReservedSubnets(opts.ReservedPools.StringList.StringList); err != nil {
return err
}

if _, err := ipam.GetExternalCIDR(liqonetutils.GetMask(options.PodCIDR.String())); err != nil {
if err := ipam.Serve(consts.IpamPort); err != nil {
return err
}

Expand Down
12 changes: 2 additions & 10 deletions cmd/liqo-controller-manager/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -675,21 +675,13 @@ func main() {
}

if !*disableInternalNetwork {
networkReconciler := &networkctrl.NetworkReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
IpamClient: ipamClient,
}
networkReconciler := networkctrl.NewNetworkReconciler(mgr.GetClient(), mgr.GetScheme(), ipamClient)
if err = networkReconciler.SetupWithManager(mgr, *networkWorkers); err != nil {
klog.Errorf("Unable to start the networkReconciler", err)
os.Exit(1)
}

ipReconciler := &ipctrl.IPReconciler{
Client: mgr.GetClient(),
Scheme: mgr.GetScheme(),
IpamClient: ipamClient,
}
ipReconciler := ipctrl.NewIPReconciler(mgr.GetClient(), mgr.GetScheme(), ipamClient)
if err = ipReconciler.SetupWithManager(ctx, mgr, *ipWorkers); err != nil {
klog.Errorf("Unable to start the ipReconciler", err)
os.Exit(1)
Expand Down
2 changes: 2 additions & 0 deletions cmd/liqoctl/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import (
_ "k8s.io/client-go/plugin/pkg/client/auth"

discoveryv1alpha1 "github.com/liqotech/liqo/apis/discovery/v1alpha1"
ipamv1alpha1 "github.com/liqotech/liqo/apis/ipam/v1alpha1"
netv1alpha1 "github.com/liqotech/liqo/apis/net/v1alpha1"
networkingv1alpha1 "github.com/liqotech/liqo/apis/networking/v1alpha1"
offloadingv1alpha1 "github.com/liqotech/liqo/apis/offloading/v1alpha1"
Expand All @@ -40,6 +41,7 @@ func init() {
utilruntime.Must(sharingv1alpha1.AddToScheme(scheme.Scheme))
utilruntime.Must(virtualkubeletv1alpha1.AddToScheme(scheme.Scheme))
utilruntime.Must(networkingv1alpha1.AddToScheme(scheme.Scheme))
utilruntime.Must(ipamv1alpha1.AddToScheme(scheme.Scheme))
}

func main() {
Expand Down
8 changes: 6 additions & 2 deletions cmd/liqonet/network-manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import (

"github.com/liqotech/liqo/internal/liqonet/network-manager/netcfgcreator"
"github.com/liqotech/liqo/internal/liqonet/network-manager/tunnelendpointcreator"
liqoconst "github.com/liqotech/liqo/pkg/consts"
"github.com/liqotech/liqo/pkg/consts"
liqoipam "github.com/liqotech/liqo/pkg/ipam"
liqonetutils "github.com/liqotech/liqo/pkg/liqonet/utils"
"github.com/liqotech/liqo/pkg/utils/args"
Expand Down Expand Up @@ -132,7 +132,7 @@ func runNetworkManager(commonFlags *liqonetCommonFlags, managerFlags *networkMan
func initializeIPAM(dynClient dynamic.Interface, managerFlags *networkManagerFlags) (*liqoipam.IPAM, error) {
ipam := liqoipam.NewIPAM()

if err := ipam.Init(liqoipam.Pools, dynClient, liqoconst.IpamPort); err != nil {
if err := ipam.Init(liqoipam.Pools, dynClient); err != nil {
return nil, err
}

Expand All @@ -153,5 +153,9 @@ func initializeIPAM(dynClient dynamic.Interface, managerFlags *networkManagerFla
return nil, err
}

if err := ipam.Serve(consts.IpamPort); err != nil {
return nil, err
}

return ipam, nil
}
1 change: 1 addition & 0 deletions deployments/liqo/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@
| ipam.additionalPools | list | `[]` | Set of additional network pools to perform the automatic address mapping in Liqo. Network pools are used to map a cluster network into another one in order to prevent conflicts. Default set of network pools is: [10.0.0.0/8, 192.168.0.0/16, 172.16.0.0/12] |
| ipam.external.enabled | bool | `false` | Use an external IPAM to allocate the IP addresses for the pods. Enabling it will disable the internal IPAM. |
| ipam.external.url | string | `""` | The URL of the external IPAM. |
| ipam.externalCIDR | string | `""` | The subnet used for the external CIDR. If empty, the default value (10.70.0.0/16) is used. |
| ipam.internal.enabled | bool | `true` | Use the default Liqo IPAM. |
| ipam.internal.image.name | string | `"ghcr.io/liqotech/ipam"` | Image repository for the IPAM pod. |
| ipam.internal.image.version | string | `""` | Custom version for the IPAM image. If not specified, the global tag is used. |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,14 +359,6 @@ rules:
- patch
- update
- watch
- apiGroups:
- net.liqo.io
resources:
- ipamstorages
verbs:
- get
- list
- watch
- apiGroups:
- net.liqo.io
resources:
Expand Down
52 changes: 52 additions & 0 deletions deployments/liqo/templates/liqo-ipam-networks.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{{- $ipamConfig := (merge (dict "name" "ipam" "module" "ipam") .) -}}
---
apiVersion: ipam.liqo.io/v1alpha1
kind: Network
metadata:
name: pod-cidr
labels:
{{- include "liqo.labels" $ipamConfig | nindent 4 }}
ipam.liqo.io/network-type: pod-cidr
ipam.liqo.io/network-not-remapped: "true"
spec:
cidr: {{ .Values.ipam.podCIDR }}
---
apiVersion: ipam.liqo.io/v1alpha1
kind: Network
metadata:
name: service-cidr
labels:
{{- include "liqo.labels" $ipamConfig | nindent 4 }}
ipam.liqo.io/network-type: service-cidr
ipam.liqo.io/network-not-remapped: "true"
spec:
cidr: {{ .Values.ipam.serviceCIDR }}
---
apiVersion: ipam.liqo.io/v1alpha1
kind: Network
metadata:
name: external-cidr
labels:
{{- include "liqo.labels" $ipamConfig | nindent 4 }}
ipam.liqo.io/network-type: external-cidr
spec:
{{- if .Values.ipam.externalCIDR }}
cidr: {{ .Values.ipam.externalCIDR }}
{{- else }}
cidr: 10.70.0.0/16
{{- end }}
---
{{- range $i, $value := .Values.ipam.reservedSubnets }}
apiVersion: ipam.liqo.io/v1alpha1
kind: Network
metadata:
name: reserved-{{ add $i 1 }}
labels:
{{- include "liqo.labels" $ipamConfig | nindent 4 }}
ipam.liqo.io/network-type: reserved
ipam.liqo.io/network-not-remapped: "true"
spec:
cidr: {{ $value }}
---
{{- end }}

2 changes: 2 additions & 0 deletions deployments/liqo/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -204,6 +204,8 @@ ipam:
podCIDR: ""
# -- The subnet used by the services in you cluster, in CIDR notation (e.g., 172.16.0.0/16).
serviceCIDR: ""
# -- The subnet used for the external CIDR. If empty, the default value (10.70.0.0/16) is used.
externalCIDR: ""
# -- List of IP subnets that do not have to be used by Liqo.
# Liqo can perform automatic IP address remapping when a remote cluster is peering with you, e.g., in case IP address spaces (e.g., PodCIDR) overlaps.
# In order to prevent IP conflicting between locally used private subnets in your infrastructure and private subnets belonging to remote clusters
Expand Down
19 changes: 19 additions & 0 deletions pkg/consts/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,26 @@

package consts

// NetworkType indicates the type of Network.
type NetworkType string

const (
// IpamPort is the port used by the IPAM gRPC server.
IpamPort = 6000

// NetworkNotRemappedLabelKey is the label key used to mark a Network that does not need CIDR remapping.
NetworkNotRemappedLabelKey = "ipam.liqo.io/network-not-remapped"
// NetworkNotRemappedLabelValue is the label value used to mark a Network that does not need CIDR remapping.
NetworkNotRemappedLabelValue = "true"

// NetworkTypeLabelKey is the label key used to indicate the type of a Network.
NetworkTypeLabelKey = "ipam.liqo.io/network-type"
// NetworkTypePodCIDR is the constant representing a network of type podCIDR.
NetworkTypePodCIDR NetworkType = "pod-cidr"
// NetworkTypeServiceCIDR is the constant representing a network of type serviceCIDR.
NetworkTypeServiceCIDR NetworkType = "service-cidr"
// NetworkTypeExternalCIDR is the constant representing a network of type externalCIDR.
NetworkTypeExternalCIDR NetworkType = "external-cidr"
// NetworkTypeReserved is the constant representing a network of type reserved subnet.
NetworkTypeReserved NetworkType = "reserved"
)
6 changes: 6 additions & 0 deletions pkg/ipam/fake/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,3 +115,9 @@ func (mock *IPAMClient) MapNetworkCIDR(_ context.Context, req *ipam.MapCIDRReque
func (mock *IPAMClient) UnmapNetworkCIDR(_ context.Context, _ *ipam.UnmapCIDRRequest, _ ...grpc.CallOption) (*ipam.UnmapCIDRResponse, error) {
return &ipam.UnmapCIDRResponse{}, nil
}

// GetOrSetExternalCIDR mocks the corresponding IPAMClient function.
func (mock *IPAMClient) GetOrSetExternalCIDR(_ context.Context, req *ipam.GetOrSetExtCIDRRequest,
_ ...grpc.CallOption) (*ipam.GetOrSetExtCIDRResponse, error) {
return &ipam.GetOrSetExtCIDRResponse{RemappedExtCIDR: req.DesiredExtCIDR}, nil
}
55 changes: 43 additions & 12 deletions pkg/ipam/ipam.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ type Ipam interface {
this function must not reserve it. If the remote cluster has not remapped
a local subnet, then CIDR value should be equal to "None". */
AddLocalSubnetsPerCluster(podCIDR, externalCIDR, clusterID string) error
// GetExternalCIDR chooses and returns the local cluster's ExternalCIDR.
GetExternalCIDR(mask uint8) (string, error)
// SetPodCIDR sets the cluster PodCIDR.
SetPodCIDR(podCIDR string) error
Expand Down Expand Up @@ -104,7 +105,7 @@ var Pools = []string{
const emptyCIDR = ""

// Init uses the Ipam resource to retrieve and allocate reserved networks.
func (liqoIPAM *IPAM) Init(pools []string, dynClient dynamic.Interface, listeningPort int) error {
func (liqoIPAM *IPAM) Init(pools []string, dynClient dynamic.Interface) error {
var err error
// Set up storage
liqoIPAM.ipamStorage, err = NewIPAMStorage(dynClient)
Expand All @@ -130,17 +131,26 @@ func (liqoIPAM *IPAM) Init(pools []string, dynClient dynamic.Interface, listenin
return fmt.Errorf("cannot set pools: %w", err)
}
}
if listeningPort > 0 {
err = liqoIPAM.initRPCServer(listeningPort)
if err != nil {
return fmt.Errorf("cannot start gRPC server: %w", err)
}
}

liqoIPAM.natMappingInflater = natmappinginflater.NewInflater(dynClient)
return nil
}

// Serve starts the gRPC server.
func (liqoIPAM *IPAM) Serve(listeningPort int) error {
if listeningPort <= 0 {
return fmt.Errorf("IPAM gRPC server not started: invalid listening port %d", listeningPort)
}

if err := liqoIPAM.initRPCServer(listeningPort); err != nil {
return fmt.Errorf("cannot start gRPC server: %w", err)
}

klog.Infof("IPAM gRPC server listening on port %d", listeningPort)

return nil
}

// Terminate function stops the gRPC server.
func (liqoIPAM *IPAM) Terminate() {
// Stop GRPC server
Expand Down Expand Up @@ -378,9 +388,8 @@ func (liqoIPAM *IPAM) clusterSubnetEqualToPool(pool string) (string, error) {
return mappedNetwork, nil
}

// MapNetworkCIDR receives a network CIDR and a cluster identifier and,
// return the network CIDR to use for the remote cluster, remapped if
// necessary.
// MapNetworkCIDR receives a network CIDR and return the network CIDR to use for the remote cluster,
// remapped if necessary.
func (liqoIPAM *IPAM) MapNetworkCIDR(_ context.Context, mapCIDRRequest *MapCIDRRequest) (*MapCIDRResponse, error) {
mappedCIDR, err := liqoIPAM.getOrRemapNetwork(mapCIDRRequest.GetCidr())
if err != nil {
Expand All @@ -389,7 +398,7 @@ func (liqoIPAM *IPAM) MapNetworkCIDR(_ context.Context, mapCIDRRequest *MapCIDRR
return &MapCIDRResponse{Cidr: mappedCIDR}, nil
}

// UnmapNetworkCIDR set the network CIDR as unused for a specific cluster.
// UnmapNetworkCIDR set the network CIDR as unused.
func (liqoIPAM *IPAM) UnmapNetworkCIDR(_ context.Context, unmapCIDRRequest *UnmapCIDRRequest) (*UnmapCIDRResponse, error) {
err := liqoIPAM.FreeReservedSubnet(unmapCIDRRequest.GetCidr())
if err != nil {
Expand All @@ -398,6 +407,28 @@ func (liqoIPAM *IPAM) UnmapNetworkCIDR(_ context.Context, unmapCIDRRequest *Unma
return &UnmapCIDRResponse{}, nil
}

// GetOrSetExternalCIDR get or set the external CIDR (eventually remapped) for the cluster.
func (liqoIPAM *IPAM) GetOrSetExternalCIDR(_ context.Context, getOrSetExtCIDRRequest *GetOrSetExtCIDRRequest) (*GetOrSetExtCIDRResponse, error) {
// Get cluster externalCIDR if already set
externalCIDR := liqoIPAM.ipamStorage.getExternalCIDR()
if externalCIDR != "" {
return &GetOrSetExtCIDRResponse{RemappedExtCIDR: externalCIDR}, nil
}

// ExternalCIDR is not set: allocate a new network (eventually remapped if conflicts are found)
externalCIDR, err := liqoIPAM.getOrRemapNetwork(getOrSetExtCIDRRequest.GetDesiredExtCIDR())
if err != nil {
return &GetOrSetExtCIDRResponse{}, fmt.Errorf("cannot map external CIDR %s: %w", getOrSetExtCIDRRequest.GetDesiredExtCIDR(), err)
}

// Update ipamstorage with the new external CIDR
if err := liqoIPAM.ipamStorage.updateExternalCIDR(externalCIDR); err != nil {
_ = liqoIPAM.FreeReservedSubnet(externalCIDR)
return &GetOrSetExtCIDRResponse{}, fmt.Errorf("cannot update external CIDR in the ipam storage: %w", err)
}
return &GetOrSetExtCIDRResponse{RemappedExtCIDR: externalCIDR}, nil
}

// getOrRemapNetwork first tries to acquire the received network.
// If conflicts are found, a new mapped network is returned.
func (liqoIPAM *IPAM) getOrRemapNetwork(network string) (string, error) {
Expand Down Expand Up @@ -1160,7 +1191,7 @@ func (liqoIPAM *IPAM) mapEndpointIPInternal(clusterID, ip string) (string, error
// MapEndpointIP receives a service endpoint IP and a cluster identifier and,
// if the endpoint IP does not belong to cluster PodCIDR, maps
// the endpoint IP to a new IP taken from the remote ExternalCIDR of the remote cluster.
func (liqoIPAM *IPAM) MapEndpointIP(ctx context.Context, mapRequest *MapRequest) (*MapResponse, error) {
func (liqoIPAM *IPAM) MapEndpointIP(_ context.Context, mapRequest *MapRequest) (*MapResponse, error) {
mappedIP, err := liqoIPAM.mapEndpointIPInternal(mapRequest.GetClusterID(), mapRequest.GetIp())
if err != nil {
return &MapResponse{}, fmt.Errorf("cannot map endpoint IP to ExternalCIDR of cluster %s, %w",
Expand Down
Loading

0 comments on commit 239dba0

Please sign in to comment.